跳至主要內容

如何集成场景

2025年7月22日大约 5 分钟

如何集成场景

集成方式

通过 iframe 方式进行页面嵌入集成, 使用 postMessage 实现通信交互。

  • 发送方通过 ${iframe}.contentWindow.postMessage() 方法发送输入消息。
  • 接收方通过监听 window 对象的 message 事件接收输出消息。

输入消息

输入消息用于外部向场景内传递执行事件动作列表, 通过事件动作可以控制场景内的实体节点进行显隐或切换状态等

消息格式

消息类型为 json 对象, 消息属性名称格式:

  • 固定名称: scene_input_message
  • 基于 window.name 的名称: ${window.name}_input_message
  • 基于场景 ID 的名称: ${场景 ID}_input_message

场景内接收优先级: 基于场景 ID 的名称 > 基于 window.name 的名称 > 固定名称。

# 固定名称
{ scene_input_message: {} }

# window.name 为 test
{ test_input_message: {} }

# 场景 ID 为 HT1234
{ HT1234_input_message: {} }

提示

非固定名称格式用于在单页面集成多个 3D 场景时区分消息归属。

消息内容

输入消息的内容为动作执行列表, 每个对象为一个场景可执行动作, 场景在接收到消息后按序执行动作对应的事件:

{
  scene_input_message: {
    actions: [];
  }
}

动作说明:

  • target: 执行目标, 可选项
    • '' / sceneEngine / 可选: 表示调用场景事件
    • activeCamera: 表示调用场景当前激活相机的事件
    • 实体节点 ID: 表示调用 ID 对应节点的事件
  • eventName: 事件名称, 详见
  • eventArgs: 事件参数, 以数组形式传入, 数组内按序添加事件参数
{
  scene_input_message: {
    actions: [
      // 设置场景激活相机为 Entity_2: Entity_2 需为相机类型节点
      {
        eventName: 'setActiveCamera',
        eventArgs: ['Entity_2']
      },
      // 设置场景激活相机的视角为 Point_1
      {
        target: 'activeCamera',
        eventName: 'setActiveViewpoint',
        eventArgs: ['Point_1']
      },
      // 设置实体节点 Entity_3 的激活状态为 State_1
      {
        target: 'Entity_3',
        eventName: 'setActiveState',
        eventArgs: ['State_1']
      }
    ];
  }
}

输出消息

输出消息用于当场景内相关节点执行事件后通知外部, 外部接收到通知消息后可根据事件源、事件名称等信息进行响应交互

消息格式

消息类型为 json 对象, 消息内容放在 hetu 属性下:

{ hetu: {} }

消息名称格式:

  • 固定名称: scene_output_message
  • 基于 window.name 的名称: ${window.name}_output_message
  • 基于场景 ID 的名称: ${场景 ID}_output_message
# 固定名称
{ hetu: { scene_output_message: {} } }

# window.name 为 test
{ hetu: { test_output_message: {} } }

# 场景 ID 为 HT1234
{ hetu: { HT1234_output_message: {} } }

提示

非固定名称格式用于在单页面集成多个 3D 场景时区分消息归属。

消息内容

属性说明:

  • source: 事件源
  • eventName: 事件名称
  • eventData: 事件数据
// 当前消息输出为:相机 Entity_1 视角发生变化事件, 相机相关数据在 eventData 中
{
  hetu: {
    scene_output_message: {
      source:'Entity_1',
      eventName: 'cameraViewChange',
      eventData: {}
    }
  }
}

交互示例

大屏

大屏集成场景主要依赖大屏内 IFrame 组件实现, 利用该组件可实现大屏与 3D 场景消息的收发交互。

准备工作

创建 3D 场景

  • 新建 3D 场景, 并给场景添加模型。
  • 在场景中新建灯光, 并给灯光添加两种状态。
  • 将 3D 场景保存并发布, 并复制分享链接地址。

创建大屏

  • 新建大屏。

  • 在大屏编辑器内找到 iframe 组件, 拖拽组件到画布上, 在属性面板配置相关数据。

    • 名称:test, 将会设置到 iframe 的 window.name名称。
    • 链接地址:3D 场景发布分享链接地址
  • 变量池 添加变量值

    • test_output_message:用于接收 3D 场景输出的消息, 命名规则:基于 window.name 的名称。
    • test_input_message:用于发送消息到 3D 场景, 命名规则:基于 window.name 的名称
  • 在 iframe 组件, 交互面板配置相关交互。

    • 向父页面传递交互变量:点击启用。
    • 绑定到变量:test_output_message
    • 数据响应-变量:test_input_message
  • 拖拽按钮组组件到画布上, 用于发送输入消息, 在属性面板配置相关数据。
    • type:这里配置的数据对应 3D 场景灯光的状态 ID
  • 拖拽多文本组件到画布上, 用于展示接收输出消息。

给场景发送输入消息

使用节点编程, 利用切换按钮事件, 向 3D 场景发送输入消息, 改变 3D 场景内实体的状态

事件 API 详见

// 转换器内逻辑
const { type } = data;
const actions = [
  {
    // 实体ID
    target: 'Entity_3',
    // API名称,
    eventName: 'setActiveState',
    // 动作参数
    eventArgs: [type]
  }
];

return {
  test_input_message: {
    actions
  }
};

接收场景输出消息

使用节点编程, 利用多文本数据导入显示 3D 场景输出消息:

  • 监听变量 test_output_message
  • 通过转换器处理数据并导入到多文本组件
// 转换器内逻辑
return [
  {
    content: JSON.stringify(data)
  }
];

效果预览

  • 通过按钮切换 3D 场景内灯光状态
  • 多文本组件实时接收 3D 场景输出数据

第三方页面

准备工作

创建 3D 场景

  • 新建 3D 场景, 并给场景添加模型。
  • 在场景中新建灯光, 并给灯光添加两种状态。
  • 将 3D 场景保存并发布, 并复制分享链接地址。

第三方页面

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>主页面</title>
  </head>

  <body>
    <h1>主页面</h1>
    <button onclick="btnClick('State_0')">状态1</button>
    <button onclick="btnClick('State_1')">状态2</button>
    <br />
    <!--  3D 场景发布分享链接地址 -->
    <iframe
      width="1800px"
      height="600px"
      id="iframe"
      src="http://ip:port/twin/share/index.html#/TJbd32b6108643485b903209e86ab525"
    ></iframe>

    <h1>场景消息:</h1>
    <h1 style="color: red; font-size: 12px" id="childrenValue"></h1>
  </body>
  <script>
    const iframe = document.getElementById('iframe');

    // 给场景发送输入消息
    function btnClick(type) {
      const data = {
        scene_input_message: {
          actions: [
            {
              // 实体ID
              target: 'Entity_3',
              // API名称,
              eventName: 'setActiveState',
              // 动作参数
              eventArgs: [type]
            }
          ]
        }
      };
      console.log(data);
      iframe.contentWindow.postMessage(data, '*');
    }

    // 接收场景输出消息
    window.addEventListener('message', function (e) {
      console.log(e.data.hetu.scene_output_message);
      if (e.data.hetu.scene_output_message) {
        const msg = JSON.stringify(e.data.hetu.scene_output_message);
        document.getElementById('childrenValue').innerText = msg;
      }
    });
  </script>
</html>

效果预览

  • 通过按钮切换 3D 场景内灯光状态
  • 场景消息文本实时接收 3D 场景输出数据
上次编辑于: 2025/7/28 10:44:15
贡献者: zhouwf,wangyahui