Я создаю компонент React, который будет отображать график, используя строку XML с mxGraph.График отображается внутри компонента, но некоторые фигуры, такие как круги, ромбы и дорожки, отображаются неправильно;вместо этого они выглядят как простые квадраты или прямоугольники.Это особенно странно, поскольку некоторые непрямоугольные фигуры (например, Документация) отображаются правильно.
График создается с использованием отредактированной версии инструмента графографирования jgraph с некоторыми настроенными фигурами:
![Customized grapheditor tool](https://i.stack.imgur.com/UyoBd.png)
Этот инструмент графического редактора идентичен эталонной реализации, только функция addGeneralPalette () была изменена в Sidebar.js
для использования наших настраиваемых фигур:
/**
* Adds the general palette to the sidebar.
*/
Sidebar.prototype.addGeneralPalette = function(expand)
{
var fns = [
this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;', 80, 80, 'Start', 'Start', null, null, 'start begin starting beginning'),
this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;', 200, 120, 'Process', 'Process', null, null, 'process proc'),
this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;', 200, 120, 'Template', 'Template', null, null, 'template temp'),
this.createVertexTemplateEntry('rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;', 200, 120, 'Decision', 'Decision', null, null, 'decision decide'),
this.createVertexTemplateEntry('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;', 200, 120, 'Documentation', 'Documentation', null, null, 'documentation doc internal'),
this.createVertexTemplateEntry('rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;', 280, 40, 'Action', 'Action', null, null, 'action'),
this.createVertexTemplateEntry('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ffb74d;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#fff3e0;fillColor=#FFFFFF;', 200, 120, 'Sub-Process', 'Sub-Process', null, null, 'subprocess sub-process sub'),
this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;', 80, 80, 'End', 'End', null, null, 'end ending conclusion resolution close'),
this.createVertexTemplateEntry('swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;', 1020, 200, 'Phase', 'Swimlane', null, null, 'swimlane organizer phase flow stage')
];
this.addPaletteFunctions('general', mxResources.get('general'), (expand != null) ? expand : true, fns);
};
И редактируем функцию Файл> Сохранить как в EditorUi.js
, чтобы напечатать XML-код графика на консоли, чтобы мы могли использовать его в другом месте:
/**
* Saves the current graph under the given filename.
*/
EditorUi.prototype.save = function(name)
{
if (name != null){
if (this.editor.graph.isEditing()){
this.editor.graph.stopEditing();
}
var xml = mxUtils.getXml(this.editor.getGraphXml());
try{
if (xml.length < MAX_REQUEST_SIZE){
//Print XML to console
console.log('The graph can be imported to mxGraph using the following XML: ');
console.log(xml);
}else{
mxUtils.alert(mxResources.get('drawingTooLarge'));
mxUtils.popup(xml);
return;
}
this.editor.setModified(false);
this.editor.setFilename(name);
this.updateDocumentTitle();
}catch (e){
this.editor.setStatus(mxUtils.htmlEntities(mxResources.get('errorSavingFile')));
}
}
};
Экспорт этого графика из инструмента графиторав результате получается следующая строка XML:
<mxGraphModel dx="1572" dy="832" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="21" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="560" width="1020" height="200" as="geometry"/></mxCell><mxCell id="20" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="340" width="1020" height="220" as="geometry"/></mxCell><mxCell id="19" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="20" width="1020" height="320" as="geometry"/></mxCell><mxCell id="9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Start" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;" vertex="1" parent="1"><mxGeometry x="220" y="30" width="80" height="80" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="Process" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;" vertex="1" parent="1"><mxGeometry x="160" y="200" width="200" height="120" as="geometry"/></mxCell><mxCell id="17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="8"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint y="730"/><mxPoint x="630" y="730"/></Array></mxGeometry></mxCell><mxCell id="4" value="Template" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="-100" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="7"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="6"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="4"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="Decision" style="rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;" vertex="1" parent="1"><mxGeometry x="170" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="6" value="Action" style="rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="145" y="630" width="280" height="40" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="7" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="7" value="Documentation" style="shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;" vertex="1" parent="1"><mxGeometry x="470" y="360" width="200" height="120" as="geometry"/></mxCell><mxCell id="8" value="End" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;" vertex="1" parent="1"><mxGeometry x="590" y="610" width="80" height="80" as="geometry"/></mxCell></root></mxGraphModel>
Теперь, в моем приложении React (полностью отделенном от инструмента grapheditor, который является автономным веб-приложением, которое не взаимодействует с моим приложением React), я беру этоXML-строка и использование mxGraph для декодирования и рендеринга в компоненте React:
import React, { Component } from "react";
//We imported mxClient et al via <script> tags in index.html
let mxGraph = window.mxGraph;
let mxUtils = window.mxUtils;
let mxEvent = window.mxEvent;
let mxRubberband = window.mxRubberband;
let mxKeyHandler = window.mxKeyHandler;
let mxCellHighlight = window.mxCellHighlight;
let mxCodec = window.mxCodec;
class App extends Component {
componentDidMount(){
var graph = new mxGraph(document.getElementById('divGraph'));
var rubberband = new mxRubberband(graph);
var keyHandler = new mxKeyHandler(graph);
var highlight = new mxCellHighlight(graph, '#999999', 10);
let xmlString = '<mxGraphModel dx="1572" dy="832" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="21" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="560" width="1020" height="200" as="geometry"/></mxCell><mxCell id="20" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="340" width="1020" height="220" as="geometry"/></mxCell><mxCell id="19" value="Phase" style="swimlane;html=1;horizontal=0;swimlaneLine=0;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=4;fillColor=#26C6DA;gradientColor=#00ACC1;fontFamily=Helvetica;fontSize=16;fontColor=#FFFFFF;gradientDirection=east;spacing=0;spacingTop=-4;swimlaneFillColor=none;collapsible=0;" vertex="1" parent="1"><mxGeometry x="-210" y="20" width="1020" height="320" as="geometry"/></mxCell><mxCell id="9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="2" target="3"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="2" value="Start" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#e8f5e9;strokeColor=#4caf50;strokeWidth=4;gradientColor=#c8e6c9;" vertex="1" parent="1"><mxGeometry x="220" y="30" width="80" height="80" as="geometry"/></mxCell><mxCell id="15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="3" value="Process" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;strokeColor=#ff9800;strokeWidth=4;perimeterSpacing=0;fontSize=16;gradientColor=#ffe0b2;fillColor=#fff3e0;" vertex="1" parent="1"><mxGeometry x="160" y="200" width="200" height="120" as="geometry"/></mxCell><mxCell id="17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="8"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint y="730"/><mxPoint x="630" y="730"/></Array></mxGeometry></mxCell><mxCell id="4" value="Template" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#00ACC1;strokeWidth=5;glass=0;comic=0;gradientColor=#b2ebf2;fillColor=#e0f7fa;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="-100" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="7"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="6"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5" target="4"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="5" value="Decision" style="rhombus;whiteSpace=wrap;html=1;rounded=0;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#333333;strokeWidth=4;fillColor=#eeeeee;gradientColor=#e5e5e5;fontFamily=Helvetica;fontSize=16;fontColor=#000000;align=center;" vertex="1" parent="1"><mxGeometry x="170" y="410" width="200" height="120" as="geometry"/></mxCell><mxCell id="18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="6" value="Action" style="rounded=1;whiteSpace=wrap;html=1;glass=0;comic=0;labelBackgroundColor=none;strokeColor=#e91e63;strokeWidth=4;fillColor=#fce4ec;gradientColor=#f8bbd0;fontFamily=Helvetica;fontSize=16;fontColor=#000000;" vertex="1" parent="1"><mxGeometry x="145" y="630" width="280" height="40" as="geometry"/></mxCell><mxCell id="12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="7" target="8"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="7" value="Documentation" style="shape=document;whiteSpace=wrap;html=1;boundedLbl=1;strokeWidth=4;strokeColor=#9C27B0;gradientColor=#E1BEE7;fillColor=#F3E5F5;fontSize=16;" vertex="1" parent="1"><mxGeometry x="470" y="360" width="200" height="120" as="geometry"/></mxCell><mxCell id="8" value="End" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;fontFamily=Helvetica;fontSize=16;fillColor=#ffebee;strokeColor=#f44336;strokeWidth=4;gradientColor=#ffcdd2;" vertex="1" parent="1"><mxGeometry x="590" y="610" width="80" height="80" as="geometry"/></mxCell></root></mxGraphModel>';
var doc = mxUtils.parseXml(xmlString);
var codec = new mxCodec(doc);
codec.decode(doc.documentElement, graph.getModel());
graph.fit();
graph.setPanning(true);
graph.setEnabled(false);
graph.setHtmlLabels(true);
//graph will listen for click events
graph.addListener(mxEvent.CLICK, (sender, event) => {
let cell = event.getProperty('cell');
if(cell != null){
//highlight the clicked cell
highlight.highlight(graph.view.getState(cell));
}
});
}
render() {
return (
<div>
<div id="divGraph"></div>
</div>
)
}
}
export default App;
В этом приложении React используется следующее index.html
, который импортирует различные библиотеки mxGraph из локального каталога:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<script type="text/javascript">mxBasePath = './mx/src'</script>
<script type="text/javascript" src="./mx/src/js/mxClient.js"></script>
<script type="text/javascript" src="./mx/Init.js"></script>
<script type="text/javascript" src="./mx/EditorUi.js"></script>
<script type="text/javascript" src="./mx/Editor.js"></script>
<script type="text/javascript" src="./mx/Sidebar.js"></script>
<script type="text/javascript" src="./mx/Graph.js"></script>
<script type="text/javascript" src="./mx/Format.js"></script>
<script type="text/javascript" src="./mx/Shapes.js"></script>
<script type="text/javascript" src="./mx/Actions.js"></script>
<script type="text/javascript" src="./mx/Menus.js"></script>
<script type="text/javascript" src="./mx/Toolbar.js"></script>
<script type="text/javascript" src="./mx/Dialogs.js"></script>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
К сожалению, когда приложение отображает график, оно выглядит так:
![incorrect rendering](https://i.stack.imgur.com/3IW1k.png)
Я не совсем уверен, к чему приписать эту проблему, так как считаю, что импортировал все необходимые библиотеки, такие как Shapes.js
и тому подобное.Я проверил документацию mxGraph и эту ветку о похожей проблеме , но импорт Shapes.js, как рекомендовано в этой ветке, похоже, не решил проблему (или я неправильно импортирую Shapes.js).
Любое понимание того, как подойти к этой проблеме, очень ценится.