问题
I'm trying use mxGraph instance in node.js to prepare XML export with my custom logic (works with front-end, i'm just moving logic to back-end). Is it possible to use full API of mxGraph instance in nodej.js, i'm wondering about methods like graph.getDefaultParent()
etc.
I'm trying load new instance using correct, generated by plugin XML, but code below won't affect on model (no other errors)
const dom = new JSDOM();
global.window = dom.window;
global.document = dom.window.document;
global.navigator = {
userAgent: '',
appName: '',
appVersion: '',
};
new JSDOM(
`<!DOCTYPE html>
<html>
<body>
<div id="container"></div>
<script type="text/javascript">
const graphInstance = new mxGraph(document.getElementById('container'));
const xmlDocument = new DOMParser().parseFromString(window.content, 'text/xml');
const node = xmlDocument.documentElement;
let decoder = new mxCodec(xmlDocument);
decoder.decode(node, graphInstance.getModel());
console.log(graphInstance.getModel()); // looks exactly like before decode
</script>
</body>
</html>`,
{
runScripts: 'dangerously',
beforeParse(window) {
const { mxGraph, mxUtils, mxCodec } = require('../../static/flow-chart/js/mxClient/js/mxClient');
window.DOMParser = require('xmldom').DOMParser;
window.content = content // mxGraph's XML, using in front-end too
.replace('</mxGraphModel>', '')
.replace('<mxGraphModel>', '');
window.mxGraph = mxGraph;
window.mxUtils = mxUtils;
window.mxCodec = mxCodec;
}
}
);
What console loge throws:
mxCell {
value: undefined,
geometry: undefined,
style: undefined,
children:
[ mxCell {
value: undefined,
geometry: undefined,
style: undefined,
parent: [Circular],
id: '1',
mxObjectId: 'mxCell#5' } ],
id: '0',
mxObjectId: 'mxCell#4' }
mxGraphModel {
currentEdit:
mxUndoableEdit {
source: [Circular],
changes: [],
significant: true,
notify: [Function] },
root:
mxCell {
value: undefined,
geometry: undefined,
style: undefined,
children: [ [Object] ],
id: '0',
mxObjectId: 'mxCell#4' },
nextId: 2,
cells:
{ '0':
mxCell {
value: undefined,
geometry: undefined,
style: undefined,
children: [Array],
id: '0',
mxObjectId: 'mxCell#4' },
'1':
mxCell {
value: undefined,
geometry: undefined,
style: undefined,
parent: [Object],
id: '1',
mxObjectId: 'mxCell#5' } },
updateLevel: 0,
endingUpdate: false,
eventListeners:
[ 'change',
[Function],
'change',
[Function],
'change',
[Function],
'change',
[Function],
'change',
[Function],
'change',
[Function] ] }
回答1:
Hi and many thanks for suggesting jsdom. The following snippet generates xml and embeds it into html:
'use strict';
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM();
global.window = dom.window;
global.document = window.document;
global.XMLSerializer = window.XMLSerializer
global.navigator = window.navigator;
var viewerModulePath = "mxgraph";
const mxgraph = require(viewerModulePath)({
// These are wrong but harmless at the moment.
mxImageBasePath: "./src/images",
mxBasePath: "./src"
});
const {mxGraph, mxCodec, mxUtils} = mxgraph;
const helloWorldGraph = makeHelloWorld();
console.log(graphToHTML(helloWorldGraph));
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;
}
function graphToXML(graph) {
var encoder = new mxCodec();
var result = encoder.encode(graph.getModel());
return mxUtils.getXml(result);
}
function graphToHTML(graph) {
const xml = graphToXML(graph);
return getHtml2(xml, "Hello World!");
}
// Extracted from https://github.com/jgraph/drawio/blob/master/src/main/webapp/js/diagramly/EditorUi.js#L1452
function getHtml2(xml, title, redirect) {
const EditorUi = {
drawHost: 'https://www.draw.io'
}
var js = EditorUi.drawHost + '/js/viewer.min.js';
var foldingEnabled = false;
// Makes XHTML compatible
if (redirect != null) {
redirect = redirect.replace(/&/g, '&');
}
var data = {highlight: '#0000ff', nav: foldingEnabled, resize: false, xml: xml, toolbar: ''};
var style = 'max-width:100%;border:1px solid transparent;';
return ((redirect == null) ? '<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=5,IE=9" ><![endif]-->\n' : '') +
'<!DOCTYPE html>\n<html' + ((redirect != null) ? ' xmlns="http://www.w3.org/1999/xhtml">' : '>') +
'\n<head>\n' + ((redirect == null) ? ((title != null) ? '<title>' + mxUtils.htmlEntities(title) +
'</title>\n' : '') : '<title>Draw.io Diagram</title>\n') +
((redirect != null) ? '<meta http-equiv="refresh" content="0;URL=\'' + redirect + '\'"/>\n' : '') +
'<meta charset="utf-8"/>\n</head>\n<body>' +
'\n<div class="mxgraph" style="' + style + '" data-mxgraph="' + mxUtils.htmlEntities(JSON.stringify(data)) + '"></div>\n' +
((redirect == null) ? '<script type="text/javascript" src="' + js + '"></script>' :
'<a style="position:absolute;top:50%;left:50%;margin-top:-128px;margin-left:-64px;" ' +
'href="' + redirect + '" target="_blank"><img border="0" ' +
'src="' + EditorUi.drawHost + '/images/drawlogo128.png"/></a>') +
'\n</body>\n</html>\n';
}
Save this in an html file for example:
npm install mxgraph jdom
node helloworld.js > helloworld.html
The layout algorithms are also working fine.
I had a shot at extracting more code from diagramly to support the SVG canvas but it felt convoluted and unmaintainable. Jsdom does support canvas so technically it should be possible to generate SVG from nodejs alone.
I hope this helps!
来源:https://stackoverflow.com/questions/55711473/how-i-can-use-mxgraph-instance-in-node-js