我和我的团队正在研究如何使用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;
}问题是:
编辑:我在程序的末尾添加了以下内容:
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);这让我得到了"Uncaught :未能在‘XMLSerializer’上执行'serializeToString‘:参数1不是’Node‘类型的。“我尝试过一些东西,但是我对mxGraph还不太熟悉,无法从我的画布中获得它所需要的节点。
发布于 2020-12-18 11:50:29
关于第1点,您可以查看draw.io代码,它提供了有关如何设置画布的详细信息。
但是这段代码打算在浏览器中使用,所以在依赖于JSDOM的脚本中运行时可能会出现问题。
您必须使用mxImageExport来使用画布。然后包装所产生的节点以生成svg字符串(在下面的svgRoot中是由自定义代码生成并由mxImageExport更新的元素)
'<?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字符串,就可以将它直接写入文件中,就像在xml文件中存储mx图模型一样。
对于浏览器中的第2点,可以使用Anchor元素(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes)的下载和href属性。
第一,生成一个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的更多细节
发布于 2020-12-31 02:35:49
要从XML生成SVG文件,您可以从http://get.diagrams.net下载桌面版本的http://get.diagrams.net并在命令行上运行它。
命令行标志的文档可以找到这里或运行draw.io --help。
/Applications/draw.io.app/Contents/MacOS/draw.io -x -f svg graph.xml但是,以这种方式生成的SVG文件缺少嵌入的XML数据,因此可以在diagrams.net中重新打开它们。可以使用regex或其他方法重新插入此数据。
https://stackoverflow.com/questions/65315250
复制相似问题