【问题标题】:Outputting SVG files from mxGraph从 mxGraph 输出 SVG 文件
【发布时间】:2020-12-31 10:35:49
【问题描述】:

我和我的团队正在研究使用 mxGraph 以编程方式生成图表。我们创建了一个图表并将其保存为 XML 文件。我们如何从那里转到 SVG 文件?

我了解 mxGraph 原生使用 SVG 文件进行显示,并且它可以编写其中包含 XML 编码的 SVG 文件,以便可以在 diagrams.net 中重新打开它们。如何让 mxGraph 将我们的图形放在 SVG 画布上,然后将其序列化到磁盘?

// from https://stackoverflow.com/a/57829704
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM();
const fs = require('fs');

global.window = dom.window;
global.document = window.document;
global.XMLSerializer = window.XMLSerializer;
global.navigator = window.navigator;

const mxgraph = require("mxgraph")({
    mxImageBasePath: "./src/images",
    mxBasePath: "./src"
});


const {mxGraph, mxCodec, mxUtils, mxConstants, mxSvgCanvas2D} = mxgraph;

function makeHelloWorld() {
  // Extracted from https://github.com/jgraph/mxgraph/blob/master/javascript/examples/helloworld.html
  const graph = new mxGraph();

  // Gets the default parent for inserting new cells. This
  // is normally the first child of the root (ie. layer 0).
  var parent = graph.getDefaultParent();

  // Adds cells to the model in a single step
  graph.getModel().beginUpdate();
  try {
    var v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);
    var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
    var e1 = graph.insertEdge(parent, null, '', v1, v2);
  } finally {
    // Updates the display
    graph.getModel().endUpdate();
  }
  return graph;
}

const helloWorldGraph = makeHelloWorld();

function graphToXML(graph) {
    var encoder = new mxCodec();
    var result = encoder.encode(graph.getModel());
    return mxUtils.getXml(result);
}

const xml = graphToXML(helloWorldGraph);

fs.writeFileSync('./graph.xml', xml);

到目前为止一切正常——我们可以输出一个 XML 文件。现在我们必须从那里得到一个 SVG。

我已经创建了一个 SVG 画布,如下所示:

function createSvgCanvas(graph) {
    const svgDoc = mxUtils.createXmlDocument();
    const root = (svgDoc.createElementNS != null) ? svgDoc.createElementNS(mxConstants.NS_SVG, 'svg') : svgDoc.createElement('svg');
    if (svgDoc.createElementNS == null) {
        root.setAttribute('xmlns', mxConstants.NS_SVG);
        root.setAttribute('xmlns:xlink', mxConstants.NS_XLINK);
    } else {
        root.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', mxConstants.NS_XLINK);
    }
    const bounds = graph.getGraphBounds();
    root.setAttribute('width', (bounds.x + bounds.width + 4) + 'px');
    root.setAttribute('height', (bounds.y + bounds.height + 4) + 'px');
    root.setAttribute('version', '1.1');
    svgDoc.appendChild(root);
    const svgCanvas = new mxSvgCanvas2D(root);
    return svgCanvas;
}

问题是:

  1. 新画布的大小适合图表,但上面还没有图表。
  2. 我需要弄清楚如何将 SVG 画布转换为磁盘上的 SVG 文件。

编辑:我在程序末尾添加了以下内容:

const canvas = createSvgCanvas(helloWorldGraph);
const imgExport = new mxImageExport();
imgExport.drawState(helloWorldGraph.getView().getState(helloWorldGraph.model.root), canvas); // adapted from https://jgraph.github.io/mxgraph/docs/js-api/files/util/mxImageExport-js.html

const xml2 = mxUtils.getXml(canvas)

const svgString = '<?xml version="1.0" encoding="UTF-8"?>\n'
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'
+ xml2
fs.writeFileSync('./graph.svg', svgString);

这让我得到“未捕获的 TypeError:无法在 'XMLSerializer' 上执行 'serializeToString':参数 1 不是 'Node' 类型。”我尝试了一些方法,但我对 mxGraph 不够熟悉,无法从我的画布中获取它需要的节点。

【问题讨论】:

    标签: javascript svg mxgraph


    【解决方案1】:

    对于第 1 点,您可以查看 draw.io 代码,该代码提供了有关如何设置画布的详细信息。

    但是这段代码是在浏览器中使用的,所以在你的依赖于 JSDOM 的脚本中运行时可能会遇到问题。

    您必须使用 mxImageExport 才能使用画布。 然后将生成的节点包裹起来生成svg字符串(下面svgRoot是自定义代码生成并由mxImageExport更新的Element)

    '<?xml version="1.0" encoding="UTF-8"?>\n'
     + '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'
     + mxUtils.getXml(svgRoot)
    

    脚本中的第 2 点 获得 svg 字符串后,您可以将其直接写入文件,就像将 mxgraph 模型存储在 xml 文件中一样。

    对于浏览器中的第 2 点 可以使用 Anchor 元素的 download 和 href 属性 (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes)

    1、生成一个href数据,其中包含点1产生的svg字符串的编码值

    'data:image/svg+xml' + encodeURIComponent(svg)
    

    然后使用此 href 数据创建锚点,并在单击按钮时触发它。 更多详情https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server

    【讨论】:

    • 感谢您的回答!用我取得的一些进展更新了我的问题。
    【解决方案2】:

    要从 XML 生成 SVG 文件,您可以从 http://get.diagrams.net 下载桌面版的 diagrams.net 并在命令行上运行。

    可以在here 或通过运行draw.io --help 找到有关命令行标志的文档。

    /Applications/draw.io.app/Contents/MacOS/draw.io -x -f svg graph.xml
    

    但是,以这种方式生成的 SVG 文件缺少嵌入的 XML 数据,因此可以在 diagrams.net 中重新打开它们。可以使用正则表达式或其他方法重新插入此数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      相关资源
      最近更新 更多