Моя команда и я рассматриваем возможность использования mxGraph для программного создания диаграмм. Мы создали график и сохранили его в виде XML-файла. Как нам перейти оттуда к файлу SVG?
Я понимаю, что mxGraph изначально использует файлы SVG для отображения и что он может записывать файлы SVG с закодированным в них XML, чтобы их можно было повторно открыть в диаграммах.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;
}
Проблемы:
- Размер нового холста соответствует графику, но на нем еще нет графика.
- Мне нужно выяснить, как превратить холст 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);
Это вызывает у меня Uncaught TypeError: не удалось выполнить «serializeToString» в «XMLSerializer»: параметр 1 не имеет типа «узел». Я пробовал кое-что, но я недостаточно знаком с mxGraph, чтобы получить нужный узел из моего холста.