山海鲸可视化

内外网页通信

集成山海鲸页面时,外部网页可以通过发送 postmessage 的形式来进行通信,同时也支持直接通过 postmessage 动态的修改属性值和触发交互。

1.同二开代码通信

最通用也是最灵活的方式就是外部发送 postmessage 给内部的二开代码,再有二开代码来决定下一步需要做什么操作,同时二开代码在收到 message 之后也可以向外部发送信息。

在前面文章集成了 iFrame 之后,我们在外部网页中再添加两个按钮,分别是白天和晚上。

我们看一下实例代码:

<html>
  <style>
    html {
      background-color: cadetblue;
    }
    .controlbar {
      display: flex;
    }
    .controlbar button {
      width: 200px;
      height: 100px;
      margin-left: 50px;
    }
  </style>
  <body>
    <iframe
      id="shanhai-frame"
      width="1600"
      height="900"
      src="http://192.168.31.136:5057/uo0cu7q95zuq/"
      frameborder="0"
      allowfullscreen="true"
    ></iframe>
    <div class="controlbar">
      <button onclick="setDaytime(12)">切换白天</button
      ><button onclick="setDaytime(0)">切换晚上</button>
    </div>
  </body>

  <script>
    let iframeLoaded = false;
    let shanhaiFrame = document.getElementById("shanhai-frame");
    shanhaiFrame.addEventListener("load", function (e) {
      iframeLoaded = true;
    });
    function setDaytime(value) {
      if (iframeLoaded) {
        const postMessageData = {
          action: "customMessage", //动作名称
          data: {
            daytime: value,
          },
        };
        shanhaiFrame.contentWindow.postMessage(postMessageData, "*");
      }
    }
  </script>
</html>

在山海鲸中,所有的组件的二开都会收到的这个 message,这里因为我们要修改鲸孪生场景上的当前时间,因此我们在鲸孪生场景上挂载以下二开代码:

二开代码内容如下:

export class SampleExtension {
  async init() {
    //监听postMessage事件
    this.element.addEventListener("message", (ev) => {
      const { data, origin, source } = ev;
      if (data.action == "customMessage") {
        const customData = data.data;
        const daytime = customData.daytime;
        this.element.setOption(["daytime"], daytime);
        // 可以通过两种形式回发信息
        // source.postMessage("Got it");
        // window.parent.postMessage("Got it", "*");
      }
    });
  }
}

我们也可以在收到了 message 之后,通过 source 对象向外部发送 postmessage,也可以直接通过 window.parent 来发送。注意这两种形式的区别在于 source 必须收到 message 之后才能发送,window.parent 可以主动发送,我们修改一下代码,向网页发送一个回传消息:

export class SampleExtension {
  async init() {
    //监听postMessage事件
    this.element.addEventListener("message", (ev) => {
      const { data, origin, source } = ev;
      if (data.action == "customMessage") {
        const customData = data.data;
        const daytime = customData.daytime;
        this.element.setOption(["daytime"], daytime);
        // 可以通过两种形式回发信息
        // source.postMessage("Got it");
        window.parent.postMessage("Got it", "*");
      }
    });
  }
}

在网页的代码中加上收消息的代码:

<html>
  <style>
    html {
      background-color: cadetblue;
    }
    .controlbar {
      display: flex;
    }
    .controlbar button {
      width: 200px;
      height: 100px;
      margin-left: 50px;
    }
  </style>
  <body>
    <iframe
      id="shanhai-frame"
      width="1600"
      height="900"
      src="http://192.168.31.136:5057/uo0cu7q95zuq/"
      frameborder="0"
      allowfullscreen="true"
    ></iframe>
    <div class="controlbar">
      <button onclick="setDaytime(12)">切换白天</button
      ><button onclick="setDaytime(0)">切换晚上</button>
    </div>
  </body>

  <script>
    let iframeLoaded = false;
    let shanhaiFrame = document.getElementById("shanhai-frame");
    shanhaiFrame.addEventListener("load", function (e) {
      iframeLoaded = true;
    });
    // 收取来自二开代码的信息
    window.addEventListener("message", (ev) => {
      const { data } = ev;
      console.log("收到信息:", data);
    });
    function setDaytime(value) {
      if (iframeLoaded) {
        const postMessageData = {
          action: "customMessage", //动作名称
          data: {
            daytime: value,
          },
        };
        shanhaiFrame.contentWindow.postMessage(postMessageData, "*");
      }
    }
  </script>
</html>

2.动态修改组件设置

我们修改一下上一节代码的结构,不使用二开代码,直接修改设置项,具体代码如下:

<html>
  <style>
    html {
      background-color: cadetblue;
    }
    .controlbar {
      display: flex;
    }
    .controlbar button {
      width: 200px;
      height: 100px;
      margin-left: 50px;
    }
  </style>
  <body>
    <iframe
      id="shanhai-frame"
      width="1600"
      height="900"
      src="http://192.168.31.136:5057/ap1guovmpedt/"
      frameborder="0"
      allowfullscreen="true"
    ></iframe>
    <div class="controlbar">
      <button onclick="setDaytime(12)">切换白天</button
      ><button onclick="setDaytime(0)">切换晚上</button>
    </div>
  </body>

  <script>
    let iframeLoaded = false;
    let shanhaiFrame = document.getElementById("shanhai-frame");
    shanhaiFrame.addEventListener("load", function (e) {
      iframeLoaded = true;
    });
    function setDaytime(value) {
      if (iframeLoaded) {
        const postMessageData = {
          action: "setOption", //动作名称
          data: {
            elementUID: ["c9ozws2ktrjk", "9lj7ryar3jjz", "scene"], //目标元素
            optionPath: ["daytime"], //目标属性
            optionValue: value, //目标值
          },
        };
        shanhaiFrame.contentWindow.postMessage(postMessageData, "*");
      }
    }
  </script>
</html>

注意这段代码主要就是向按了按钮之后向山海鲸的页面中发送 postmessage,其中 elementUID 是我们需要修改的目标元素的 UID,我们可以通过点击对应的元素,然后再右侧面板中点击更多选项卡,可以看到 elementUID:

另外 optionPath 则是和其他二开一样,找到对应的属性,鼠标移动上去后,点击三个点,选择菜单中的调用代码示例:

弹出框中复制 getOption 或者 setOption 的第一个参数即可:

最终网页效果如下:

点击了切换晚上后得到以下结果:

3.动态触发交互

此功能暂未开放。