You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何向嵌入模式的diagrams.net发送布局动作以初始化XML内容的布局?

如何向嵌入模式的diagrams.net发送布局动作以初始化XML内容的布局?

我来帮你梳理下正确的操作思路,解决你在嵌入模式下触发diagrams.net布局的问题:

先理清你之前遇到的问题

  1. 「Not a diagram file」报错:这是因为你在ready事件触发后直接发送布局消息,但此时diagrams.net的iframe还在等待接收XML图表内容,它把你发送的JSON格式布局指令当成XML去解析,自然就报错了。
  2. 没有直接触发布局的URL参数:确实不存在layout=1这类URL参数,所以还是得通过postMessage的方式来实现布局触发。

正确的操作流程

情况1:自动初始化布局(加载XML后自动布局)

这是你最需要的场景——加载XML内容后自动应用布局,步骤如下:

  1. 先发送XML内容加载图表
    首先必须让diagrams.net先加载你的XML图表,这是触发布局的前提:

    const iframe = document.getElementById('drawio-iframe');
    // 替换成你实际的图表XML内容
    const yourDiagramXml = '<your-full-diagram-xml-content>';
    
    // 构造加载XML的消息并发送
    const loadMessage = JSON.stringify({
      action: 'load',
      xml: yourDiagramXml
    });
    iframe.contentWindow.postMessage(loadMessage, '*');
    
  2. 监听图表加载完成信号,再发送布局指令
    当diagrams.net成功加载完图表后,会向父页面发送包含status: 'ready'的消息,我们监听这个消息后再发送布局动作:

    window.addEventListener('message', function(event) {
      const iframe = document.getElementById('drawio-iframe');
      // 只处理来自目标iframe的消息,避免跨源干扰
      if (event.source !== iframe.contentWindow) return;
    
      // 识别图表加载完成的信号
      if (typeof event.data === 'object' && event.data.status === 'ready') {
        console.log('图表加载完成,自动执行布局');
        // 构造布局指令
        const layoutMessage = JSON.stringify({
          action: 'layout',
          layouts: [
            {
              type: 'horizontalFlow',
              animate: true
            }
          ]
        });
        iframe.contentWindow.postMessage(layoutMessage, '*');
      }
    });
    

情况2:手动触发布局(比如通过按钮或自定义信号)

如果你是像之前尝试的那样,通过监听自定义的layout信号来触发布局,那要确保此时图表已经加载完成,再发送布局消息,修改你的代码示例如下:

window.addEventListener('message', function(event) {
  const iframe = document.getElementById('drawio-iframe');
  // 只处理来自目标iframe的消息
  if (event.source !== iframe.contentWindow) return;

  // 监听自定义的布局触发信号
  if (typeof event.data === 'string' && event.data.includes('layout')) {
    // 先确认图表是否已加载完成,也可以提前存储加载完成的状态
    console.log('手动触发布局');
    const layoutMessage = JSON.stringify({
      action: 'layout',
      layouts: [
        {
          type: 'horizontalFlow',
          animate: true
        }
      ]
    });
    iframe.contentWindow.postMessage(layoutMessage, '*');
  }
});

额外注意点

  • 布局的type参数可以根据需求调整,比如verticalFlow(垂直流布局)、tree(树形布局)等,对应diagrams.net内置的各种布局类型。
  • 确保你的iframe嵌入URL是正确的嵌入模式格式,比如:https://embed.diagrams.net/?embed=1&ui=minimal&toolbar=0(可根据需求调整UI参数)。
  • 如果需要针对特定元素布局,可以在layouts里添加cells参数,传入需要布局的元素ID数组,比如cells: ['cell-1', 'cell-2'],默认会对全图元素应用布局。

备注:内容来源于stack exchange,提问作者Stefan

火山引擎 最新活动