网络拓扑图本来已经整理有一段时间了,一次项目会议写集中边界监控系统的时候上级要求使用可以在系统中画网络拓扑图,没办法当时找不到现有的程序来参考 只能硬着头皮,顶着风险来完成[当然来边界安全的,当然要安全型高啊],一同事找到一些源码来分析,当然了有源码分析比自己想的效率要快得多 但是也很让人头痛,怎样才能实现,怎样才能嵌入到Web项目中? 这个集控那个项目已近完成有一段时间了,最近呢一些网友要借鉴我修改后的代码,和一些效果我最近整理了一份但是当时由于比较忙,没有发到博客中 去!只是写了一个简单的Demo供参考和利用,由于最近又有一些朋友也来问这个问题,为了方便与资源共享,我还是整理了这边文章,和网络拓扑的运用,当然 技术肯定还有更加优化好的控件,有的话希望共同学习! 下面是我编写的一个简单的Demo

这是简单画的一个拓扑图:

这是简单的绘画界面,Tab切换后是快捷键保存的后的模板[类似图表,也可以编辑],在这里就先不演示了

当然如果需要,请加入群直接下载分享文件[完整的Demo]

下面来详解下文件的配置,和代码分析

首先来看下web.xml

 
 1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
3 <display-name></display-name>
4 <servlet>
5 <description>This is the description of my J2EE component</description>
6 <display-name>This is the display name of my J2EE component</display-name>
7 <servlet-name>SaveToXmlServlet</servlet-name>
8 <servlet-class>grapheditor.SaveToXmlServlet</servlet-class>
9 </servlet>
10 <servlet-mapping>
11 <servlet-name>SaveToXmlServlet</servlet-name>
12 <url-pattern>/SaveToXmlServlet</url-pattern>
13 </servlet-mapping>
14 <welcome-file-list>
15 <welcome-file>graph.jsp</welcome-file>
16 </welcome-file-list>
17 </web-app>
 

配置不多,相信熟练Web的开发的这个就不用解释了,一看便能理解其中的配置,这里就不详细介绍了

接着我们来编写JSP页面,这里为了方便看和传输数据,我JS接直接放到一起了

 
  1 <%@ page language="java" %>
2 <%@ page contentType="text/html; charset=utf-8"%>
3 <%String path =request.getContextPath();%>
4 <head>
5 <head>
6 <title>Graph Editor</title>
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8 <script type="text/javascript" src="../../../../js/default/jquery-1.6.2.js"></script>
9 <script type="text/javascript" src="../../../../js/default/jquery-ui-1.8.16.custom.min.js"></script>
10 <link rel="stylesheet" type="text/css" href="styles/grapheditor.css">
11 <script type="text/javascript">
12 //全局变量
13 var MAX_REQUEST_SIZE = 10485760;
14 var MAX_WIDTH = 6000;
15 var MAX_HEIGHT = 6000;
16
17 //保存地址或导入地址
18 var EXPORT_URL = '/visecMc/ExportServlet';
19 var SAVE_URL = '/visecMc/SaveMapServlet';
20 var OPEN_URL = '/open';
21 var RESOURCES_PATH = 'resources';
22 var RESOURCE_BASE = RESOURCES_PATH + '/grapheditor';
23 var STENCIL_PATH = 'stencils';
24 var IMAGE_PATH = 'images';
25 var STYLE_PATH = 'styles';
26 var CSS_PATH = 'styles';
27 var OPEN_FORM = 'open.html';
28
29 //指定连接模式为触摸设备(至少有一个应该是正确的)
30 var tapAndHoldStartsConnection = true;
31 var showConnectorImg = true;
32
33 // 解析URL参数。支持参数:
34 // - lang = xy:指定用户界面的语言。
35 // - 触摸= 1:使touch-style用户界面。
36 // - 存储=当地:支持HTML5本地存储。
37 var urlParams = (function(url)
38 {
39 var result = new Object();
40 var idx = url.lastIndexOf('?');
41
42 if (idx > 0)
43 {
44 var params = url.substring(idx + 1).split('&');
45
46 for (var i = 0; i < params.length; i++)
47 {
48 idx = params[i].indexOf('=');
49
50 if (idx > 0)
51 {
52 result[params[i].substring(0, idx)] = params[i].substring(idx + 1);
53 }
54 }
55 }
56
57 return result;
58 })(window.location.href);
59
60 // 设置用户界面语言的基本路径,通过URL参数和配置
61 // 支持的语言,以避免404年代。装运的所有核心语言
62 // 资源是禁用grapheditor所需的所有资源。
63 // 属性。注意,在这个例子中两个资源的加载
64 // 文件(特殊包,默认包)是禁用的
65 // 保存一个GET请求。这就要求所有资源存在
66 // 每个属性文件,因为只有一个文件被加载。
67 mxLoadResources = false;
68 mxBasePath = '../../../src';
69 mxLanguage = urlParams['lang'];
70 mxLanguages = ['de'];
71 </script>
72 <script type="text/javascript" src="js/mxClient.js"></script>
73 <script type="text/javascript" src="js/Editor.js"></script>
74 <script type="text/javascript" src="js/Graph.js"></script>
75 <script type="text/javascript" src="js/Shapes.js"></script>
76 <script type="text/javascript" src="js/EditorUi.js"></script>
77 <script type="text/javascript" src="js/Actions.js"></script>
78 <script type="text/javascript" src="js/Menus.js"></script>
79 <script type="text/javascript" src="js/Sidebar.js"></script>
80 <script type="text/javascript" src="js/Toolbar.js"></script>
81 <script type="text/javascript" src="js/Dialogs.js"></script>
82 <script type="text/javascript" src="jscolor/jscolor.js"></script>
83 </head>
84 <body class="geEditor">
85 <input type="hidden" id="mapTp" value="qsy"/>
86 <input type="hidden" id="path" value="<%=path %>"/>
87 <script type="text/javascript">
88 // EditorUi更新扩展I / O操作状态
89 (function()
90 {
91 var editorUiInit = EditorUi.prototype.init;
92
93 EditorUi.prototype.init = function()
94 {
95 editorUiInit.apply(this, arguments);
96 //this.actions.get('export').setEnabled(false);
97 //需要一个后端更新动作状态
98 if (!useLocalStorage)
99 {
100 mxUtils.post(OPEN_URL, '', mxUtils.bind(this, function(req)
101 {
102 var enabled = req.getStatus() != 404;
103 this.actions.get('open').setEnabled(enabled || fileSupport);
104 this.actions.get('import').setEnabled(enabled || fileSupport);
105 this.actions.get('save').setEnabled(true);
106 }));
107 }
108 };
109 })();
110
111 new EditorUi(new Editor());
112 </script>
113 </body>
 

上诉文件呢,主要负责拓扑图的绘画与相关操作界面的代码

由于相关的文件过多,我这里之举出比较重要的几个问文件

Actions.js主要获取坐标并进行处理的JS文件

 
  1 function Actions(editorUi)
2 {
3 this.editorUi = editorUi;
4 this.actions = new Object();
5 this.init();
6 };
7
8 /**
9 * 添加默认的行为
10 */
11 Actions.prototype.init = function()
12 {
13 var ui = this.editorUi;
14 var editor = ui.editor;
15 var graph = editor.graph;
16 graph.cellsMovable=!0;//设置不可移动
17 graph.cellsDisconnectable=!0;//设置边不可编辑
18 graph.cellsResizable=!0;//设置不可改变大小
19 $.post($("#path").val()+"/SaveToXmlServlet",{"tp":$("#mapTp").val(),"type":"get"},function(text){
20 if(text=="0"){
21 alert("文件加载失败!");
22 }else{
23 var xml = text;
24 var doc = mxUtils.parseXml(xml);
25 var model = new mxGraphModel();
26 var codec = new mxCodec(doc);
27 codec.decode(doc.documentElement, model);
28 var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
29 graph.setSelectionCells(editor.graph.importCells(children));
30 }
31 });
32
33 // 文件操作
34 this.addAction('new', function() { window.open(ui.getUrl()); });
35 this.addAction('open', function()
36 {
37 window.openNew = true;
38 window.openKey = 'open';
39
40 ui.openFile();
41 });
42 this.addAction('import', function()
43 {
44 window.openNew = false;
45 window.openKey = 'import';
46
47 // 后关闭对话框打开
48 window.openFile = new OpenFile(mxUtils.bind(this, function()
49 {
50 ui.hideDialog();
51 }));
52
53 window.openFile.setConsumer(mxUtils.bind(this, function(xml, filename)
54 {
55 try
56 {
57 var doc = mxUtils.parseXml(xml);
58 var model = new mxGraphModel();
59 var codec = new mxCodec(doc);
60 codec.decode(doc.documentElement, model);
61
62 var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
63 editor.graph.setSelectionCells(editor.graph.importCells(children));
64 }
65 catch (e)
66 {
67 mxUtils.alert(mxResources.get('invalidOrMissingFile') + ': ' + e.message);
68 }
69 }));
70
71 // 删除openFile是否关闭对话框
72 ui.showDialog(new OpenDialog(this).container, 300, 180, true, true, function()
73 {
74 window.openFile = null;
75 });
76 });
77 this.addAction('save', function() { ui.save(); }, null, null, 'Ctrl+S');
78 //addAction(saveAs,函数(){ ui.saveFile(真正);},空,空,“Ctrl + Shift-S”);
79 //addAction(“出口”,函数(){ ui。showDialog(新ExportDialog(ui)。容器、300、200,真的,真的);},空,空,“Ctrl + E”);
80 //(“editFile”,新的行动(mxResources.get(“编辑”),mxUtils。绑定(此功能()
81 //(“editFile”,新的行动(mxResources.get(“编辑”),mxUtils。绑定(此功能()
82 this.addAction('pageSetup', function() { ui.showDialog(new PageSetupDialog(ui).container, 300, 200, true, true); });
83 this.addAction('print', function() { ui.showDialog(new PrintDialog(ui).container, 300, 200, true, true); }, null, 'sprite-print', 'Ctrl+P');
84 this.addAction('preview', function() { mxUtils.show(graph, null, 10, 10); });
85
86 // Edit actions
87 this.addAction('undo', function() { editor.undoManager.undo(); }, null, 'sprite-undo', 'Ctrl+Z');
88 this.addAction('redo', function() { editor.undoManager.redo(); }, null, 'sprite-redo', 'Ctrl+Y');
89 this.addAction('cut', function() { mxClipboard.cut(graph); }, null, 'sprite-cut', 'Ctrl+X');
90 this.addAction('copy', function() { mxClipboard.copy(graph); }, null, 'sprite-copy', 'Ctrl+C');
91 this.addAction('paste', function() { mxClipboard.paste(graph); }, false, 'sprite-paste', 'Ctrl+V');
92 this.addAction('delete', function() { graph.removeCells(); }, null, null, 'Delete');
93 this.addAction('duplicate', function()
94 {
95 var s = graph.gridSize;
96 graph.setSelectionCells(graph.moveCells(graph.getSelectionCells(), s, s, true));
97 }, null, null, 'Ctrl+D');
98 this.addAction('selectVertices', function() { graph.selectVertices(); }, null, null, 'Ctrl+Shift+V');
99 this.addAction('selectEdges', function() { graph.selectEdges(); }, null, null, 'Ctrl+Shift+E');
100 this.addAction('selectAll', function() { graph.selectAll(); }, null, null, 'Ctrl+A');
101
102 // 导航
103 this.addAction('home', function() { graph.home(); }, null, null, 'Home');
104 this.addAction('exitGroup', function() { graph.exitGroup(); }, null, null, 'Page Up');
105 this.addAction('enterGroup', function() { graph.enterGroup(); }, null, null, 'Page Down');
106 this.addAction('expand', function() { graph.foldCells(false); }, null, null, 'Enter');
107 this.addAction('collapse', function() { graph.foldCells(true); }, null, null, 'Backspace');
108
109 //安排操作
110 this.addAction('toFront', function() { graph.orderCells(false); }, null, null, 'Ctrl+F');
111 this.addAction('toBack', function() { graph.orderCells(true); }, null, null, 'Ctrl+B');
112 this.addAction('group', function() { graph.setSelectionCell(graph.groupCells(null, 0)); }, null, null, 'Ctrl+G');
113 this.addAction('ungroup', function() { graph.setSelectionCells(graph.ungroupCells()); }, null, null, 'Ctrl+U');
114 this.addAction('removeFromGroup', function() { graph.removeCellsFromParent(); });
115 this.addAction('editLink', function()
116 {
117 var cell = graph.getSelectionCell();
118 var link = graph.getLinkForCell(cell);
119
120 if (link == null)
121 {
122 link = '';
123 }
124
125 link = mxUtils.prompt(mxResources.get('enterValue'), link);
126
127 if (link != null)
128 {
129 graph.setLinkForCell(cell, link);
130 }
131 });
132 this.addAction('openLink', function()
133 {
134 var cell = graph.getSelectionCell();
135 var link = graph.getLinkForCell(cell);
136
137 if (link != null)
138 {
139 window.open(link);
140 }
141 });
142 this.addAction('autosize', function()
143 {
144 var cells = graph.getSelectionCells();
145
146 if (cells != null)
147 {
148 graph.getModel().beginUpdate();
149 try
150 {
151 for (var i = 0; i < cells.length; i++)
152 {
153 var cell = cells[i];
154
155 if (graph.getModel().getChildCount(cell))
156 {
157 graph.updateGroupBounds([cell], 20);
158 }
159 else
160 {
161 graph.updateCellSize(cell);
162 }
163 }
164 }
165 finally
166 {
167 graph.getModel().endUpdate();
168 }
169 }
170 });
171 this.addAction('rotation', function()
172 {
173 var value = '0';
174 var state = graph.getView().getState(graph.getSelectionCell());
175
176 if (state != null)
177 {
178 value = state.style[mxConstants.STYLE_ROTATION] || value;
179 }
180
181 value = mxUtils.prompt(mxResources.get('enterValue') + ' (' +
182 mxResources.get('rotation') + ' 0-360)', value);
183
184 if (value != null)
185 {
186 graph.setCellStyles(mxConstants.STYLE_ROTATION, value);
187 }
188 });
189 this.addAction('rotate', function()
190 {
191 var cells = graph.getSelectionCells();
192
193 if (cells != null)
194 {
195 graph.getModel().beginUpdate();
196 try
197 {
198 for (var i = 0; i < cells.length; i++)
199 {
200 var cell = cells[i];
201
202 if (graph.getModel().isVertex(cell) && graph.getModel().getChildCount(cell) == 0)
203 {
204 var geo = graph.getCellGeometry(cell);
205
206 if (geo != null)
207 {
208 // 旋转几何图形的大小和位置
209 geo = geo.clone();
210 geo.x += geo.width / 2 - geo.height / 2;
211 geo.y += geo.height / 2 - geo.width / 2;
212 var tmp = geo.width;
213 geo.width = geo.height;
214 geo.height = tmp;
215 graph.getModel().setGeometry(cell, geo);
216
217 //读取当前的方向并提出90度
218 var state = graph.view.getState(cell);
219
220 if (state != null)
221 {
222 var dir = state.style[mxConstants.STYLE_DIRECTION] || 'east'/*default*/;
223
224 if (dir == 'east')
225 {
226 dir = 'south';
227 }
228 else if (dir == 'south')
229 {
230 dir = 'west';
231 }
232 else if (dir == 'west')
233 {
234 dir = 'north';
235 }
236 else if (dir == 'north')
237 {
238 dir = 'east';
239 }
240
241 graph.setCellStyles(mxConstants.STYLE_DIRECTION, dir, [cell]);
242 }
243 }
244 }
245 }
246 }
247 finally
248 {
249 graph.getModel().endUpdate();
250 }
251 }
252 }, null, null, 'Ctrl+R');
253
254 //视图操作
255 this.addAction('actualSize', function()
256 {
257 graph.zoomTo(1);
258 });
259 this.addAction('zoomIn', function() { graph.zoomIn(); }, null, null, 'Add');
260 this.addAction('zoomOut', function() { graph.zoomOut(); }, null, null, 'Subtract');
261 this.addAction('fitWindow', function() { graph.fit(); });
262
263 this.addAction('fitPage', mxUtils.bind(this, function()
264 {
265 if (!graph.pageVisible)
266 {
267 this.get('pageView').funct();
268 }
269 var fmt = graph.pageFormat;
270 var ps = graph.pageScale;
271 var cw = graph.container.clientWidth - 20;
272 var ch = graph.container.clientHeight - 20;
273
274 var scale = Math.floor(100 * Math.min(cw / fmt.width / ps, ch / fmt.height / ps)) / 100;
275 graph.zoomTo(scale);
276
277 graph.container.scrollLeft = Math.round(graph.view.translate.x * scale - Math.max(10, (graph.container.clientWidth - fmt.width * ps * scale) / 2));
278 graph.container.scrollTop = Math.round(graph.view.translate.y * scale - Math.max(10, (graph.container.clientHeight - fmt.height * ps * scale) / 2));
279 }));
280 this.addAction('fitPageWidth', mxUtils.bind(this, function()
281 {
282 if (!graph.pageVisible)
283 {
284 this.get('pageView').funct();
285 }
286
287 var fmt = graph.pageFormat;
288 var ps = graph.pageScale;
289 var cw = graph.container.clientWidth - 20;
290
291 var scale = Math.floor(100 * cw / fmt.width / ps) / 100;
292 graph.zoomTo(scale);
293
294 graph.container.scrollLeft = Math.round(graph.view.translate.x * scale - Math.max(10, (graph.container.clientWidth - fmt.width * ps * scale) / 2));
295 graph.container.scrollTop = Math.round(graph.view.translate.y * scale - Math.max(10, (graph.container.clientHeight - fmt.height * ps * scale) / 2));
296 }));
297 this.put('customZoom', new Action(mxResources.get('custom'), function()
298 {
299 var value = mxUtils.prompt(mxResources.get('enterValue') + ' (%)', parseInt(graph.getView().getScale() * 100));
300
301 if (value != null && value.length > 0 && !isNaN(parseInt(value)))
302 {
303 graph.zoomTo(parseInt(value) / 100);
304 }
305 }));
306
307 //选择操作
308 var action = null;
309 action = this.addAction('grid', function()
310 {
311 graph.setGridEnabled(!graph.isGridEnabled());
312 editor.updateGraphComponents();
313 }, null, null, 'Ctrl+Shift+G');
314 action.setToggleAction(true);
315 action.setSelectedCallback(function() { return graph.isGridEnabled(); });
316 action = this.addAction('guides', function() { graph.graphHandler.guidesEnabled = !graph.graphHandler.guidesEnabled; });
317 action.setToggleAction(true);
318 action.setSelectedCallback(function() { return graph.graphHandler.guidesEnabled; });
319 action = this.addAction('tooltips', function()
320 {
321 graph.tooltipHandler.setEnabled(!graph.tooltipHandler.isEnabled());
322 });
323 action.setToggleAction(true);
324 action.setSelectedCallback(function() { return graph.tooltipHandler.isEnabled(); });
325 action = this.addAction('navigation', function()
326 {
327 graph.foldingEnabled = !graph.foldingEnabled;
328 graph.view.revalidate();
329 });
330 action.setToggleAction(true);
331 action.setSelectedCallback(function() { return graph.foldingEnabled; });
332 action = this.addAction('scrollbars', function()
333 {
334 graph.scrollbars = !graph.scrollbars;
335 editor.updateGraphComponents();
336
337 if (!graph.scrollbars)
338 {
339 var t = graph.view.translate;
340 graph.view.setTranslate(t.x - graph.container.scrollLeft / graph.view.scale, t.y - graph.container.scrollTop / graph.view.scale);
341 graph.container.scrollLeft = 0;
342 graph.container.scrollTop = 0;
343 graph.sizeDidChange();
344 }
345 else
346 {
347 var dx = graph.view.translate.x;
348 var dy = graph.view.translate.y;
349
350 graph.view.translate.x = 0;
351 graph.view.translate.y = 0;
352 graph.sizeDidChange();
353 graph.container.scrollLeft -= Math.round(dx * graph.view.scale);
354 graph.container.scrollTop -= Math.round(dy * graph.view.scale);
355 }
356 }, !mxClient.IS_TOUCH);
357 action.setToggleAction(true);
358 action.setSelectedCallback(function() { return graph.container.style.overflow == 'auto'; });
359 action = this.addAction('pageView', mxUtils.bind(this, function()
360 {
361 graph.pageVisible = !graph.pageVisible;
362 graph.pageBreaksVisible = graph.pageVisible;
363 graph.preferPageSize = graph.pageBreaksVisible;
364 graph.view.validate();
365 graph.sizeDidChange();
366
367 editor.updateGraphComponents();
368 editor.outline.update();
369
370 if (mxUtils.hasScrollbars(graph.container))
371 {
372 if (graph.pageVisible)
373 {
374 graph.container.scrollLeft -= 20;
375 graph.container.scrollTop -= 20;
376 }
377 else
378 {
379 graph.container.scrollLeft += 20;
380 graph.container.scrollTop += 20;
381 }
382 }
383 }));
384 action.setToggleAction(true);
385 action.setSelectedCallback(function() { return graph.pageVisible; });
386 this.put('pageBackgroundColor', new Action(mxResources.get('backgroundColor'), function()
387 {
388 var apply = function(color)
389 {
390 graph.background = color;
391 editor.updateGraphComponents();
392 };
393
394 var cd = new ColorDialog(ui, graph.background || 'none', apply);
395 ui.showDialog(cd.container, 220, 360, true, false);
396
397 if (!mxClient.IS_TOUCH)
398 {
399 cd.colorInput.focus();
400 }
401 }));
402 action = this.addAction('connect', function()
403 {
404 graph.setConnectable(!graph.connectionHandler.isEnabled());
405 }, null, null, 'Ctrl+Q');
406 action.setToggleAction(true);
407 action.setSelectedCallback(function() { return graph.connectionHandler.isEnabled(); });
408
409
410 this.addAction('help', function()
411 {
412 var ext = '';
413
414 if (mxResources.isLanguageSupported(mxClient.language))
415 {
416 ext = '_' + mxClient.language;
417 }
418
419 window.open(RESOURCES_PATH + '/help' + ext + '.html');
420 });
421 this.put('about', new Action(mxResources.get('about') + ' Graph Editor', function()
422 {
423 ui.showDialog(new AboutDialog(ui).container, 320, 280, true, true);
424 }, null, null, 'F1'));
425
426 //风格
427 var toggleFontStyle = mxUtils.bind(this, function(key, style)
428 {
429 this.addAction(key, function()
430 {
431 graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, style);
432 });
433 });
434
435 toggleFontStyle('bold', mxConstants.FONT_BOLD);
436 toggleFontStyle('italic', mxConstants.FONT_ITALIC);
437 toggleFontStyle('underline', mxConstants.FONT_UNDERLINE);
438
439 //颜色
440 this.addAction('fontColor', function() { ui.menus.pickColor(mxConstants.STYLE_FONTCOLOR); });
441 this.addAction('strokeColor', function() { ui.menus.pickColor(mxConstants.STYLE_STROKECOLOR); });
442 this.addAction('fillColor', function() { ui.menus.pickColor(mxConstants.STYLE_FILLCOLOR); });
443 this.addAction('gradientColor', function() { ui.menus.pickColor(mxConstants.STYLE_GRADIENTCOLOR); });
444 this.addAction('backgroundColor', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BACKGROUNDCOLOR); });
445 this.addAction('borderColor', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BORDERCOLOR); });
446
447 // 格式
448 this.addAction('shadow', function() { graph.toggleCellStyles(mxConstants.STYLE_SHADOW); });
449 this.addAction('dashed', function() { graph.toggleCellStyles(mxConstants.STYLE_DASHED); });
450 this.addAction('rounded', function() { graph.toggleCellStyles(mxConstants.STYLE_ROUNDED); });
451 this.addAction('style', function()
452 {
453 var cells = graph.getSelectionCells();
454
455 if (cells != null && cells.length > 0)
456 {
457 var model = graph.getModel();
458 var style = mxUtils.prompt(mxResources.get('enterValue')+ ' (' + mxResources.get('style') + ')',
459 model.getStyle(cells[0]) || '');
460
461 if (style != null)
462 {
463 graph.setCellStyle(style, cells);
464 }
465 }
466 });
467 this.addAction('setAsDefaultEdge', function()
468 {
469 var cell = graph.getSelectionCell();
470
471 if (cell != null && graph.getModel().isEdge(cell))
472 {
473 //目前采取的快照单元的调用
474 var proto = graph.getModel().cloneCells([cell])[0];
475
476 //删除条目- / exitXY风格
477 var style = proto.getStyle();
478 style = mxUtils.setStyle(style, mxConstants.STYLE_ENTRY_X, '');
479 style = mxUtils.setStyle(style, mxConstants.STYLE_ENTRY_Y, '');
480 style = mxUtils.setStyle(style, mxConstants.STYLE_EXIT_X, '');
481 style = mxUtils.setStyle(style, mxConstants.STYLE_EXIT_Y, '');
482 proto.setStyle(style);
483
484 //使用连接的边缘模板预览
485 graph.connectionHandler.createEdgeState = function(me)
486 {
487 return graph.view.createState(proto);
488 };
489
490 //从边缘模板创建新连接
491 graph.connectionHandler.factoryMethod = function()
492 {
493 return graph.cloneCells([proto])[0];
494 };
495 }
496 });
497 this.addAction('image', function()
498 {
499 function updateImage(value, w, h)
500 {
501 var select = null;
502 var cells = graph.getSelectionCells();
503
504 graph.getModel().beginUpdate();
505 try
506 {
507 //如果没有选中单元格插入新的细胞
508 if (cells.length == 0)
509 {
510 var gs = graph.getGridSize();
511 cells = [graph.insertVertex(graph.getDefaultParent(), null, '', gs, gs, w, h)];
512 select = cells;
513 }
514
515 graph.setCellStyles(mxConstants.STYLE_IMAGE, value, cells);
516 graph.setCellStyles(mxConstants.STYLE_SHAPE, 'image', cells);
517
518 if (graph.getSelectionCount() == 1)
519 {
520 if (w != null && h != null)
521 {
522 var cell = cells[0];
523 var geo = graph.getModel().getGeometry(cell);
524
525 if (geo != null)
526 {
527 geo = geo.clone();
528 geo.width = w;
529 geo.height = h;
530 graph.getModel().setGeometry(cell, geo);
531 }
532 }
533 }
534 }
535 finally
536 {
537 graph.getModel().endUpdate();
538 }
539
540 if (select != null)
541 {
542 graph.setSelectionCells(select);
543 graph.scrollCellToVisible(select[0]);
544 }
545 };
546
547 var value = '';
548 var state = graph.getView().getState(graph.getSelectionCell());
549
550 if (state != null)
551 {
552 value = state.style[mxConstants.STYLE_IMAGE] || value;
553 }
554
555 value = mxUtils.prompt(mxResources.get('enterValue') + ' (' + mxResources.get('url') + ')', value);
556
557 if (value != null)
558 {
559 if (value.length > 0)
560 {
561 var img = new Image();
562
563 img.onload = function()
564 {
565 updateImage(value, img.width, img.height);
566 };
567 img.onerror = function()
568 {
569 mxUtils.alert(mxResources.get('fileNotFound'));
570 };
571
572 img.src = value;
573 }
574 }
575 });
576 };
577
578 /**
579 * 注册名字下行动。
580 */
581 Actions.prototype.addAction = function(key, funct, enabled, iconCls, shortcut)
582 {
583 return this.put(key, new Action(mxResources.get(key), funct, enabled, iconCls, shortcut));
584 };
585
586 /**
587 *注册名字下行动。
588 */
589 Actions.prototype.put = function(name, action)
590 {
591 this.actions[name] = action;
592
593 return action;
594 };
595
596 /**
597 * 返回给定名称的行动或null如果没有这样的行动存在。
598 */
599 Actions.prototype.get = function(name)
600 {
601 return this.actions[name];
602 };
603
604 /**
605 * 构造一个新的行动为给定的参数。
606 */
607 function Action(label, funct, enabled, iconCls, shortcut)
608 {
609 mxEventSource.call(this);
610 this.label = label;
611 this.funct = funct;
612 this.enabled = (enabled != null) ? enabled : true;
613 this.iconCls = iconCls;
614 this.shortcut = shortcut;
615 };
616
617 //行动继承自mxEventSource
618 mxUtils.extend(Action, mxEventSource);
619
620 Action.prototype.setEnabled = function(value)
621 {
622 if (this.enabled != value)
623 {
624 this.enabled = value;
625 this.fireEvent(new mxEventObject('stateChanged'));
626 }
627 };
628
629 Action.prototype.setToggleAction = function(value)
630 {
631 this.toggleAction = value;
632 };
633
634 Action.prototype.setSelectedCallback = function(funct)
635 {
636 this.selectedCallback = funct;
637 };
638
639 Action.prototype.isSelected = function()
640 {
641 return this.selectedCallback();
642 };
 

进行坐标分配的XML文件集以及相应的图标

以一个数据库图标的坐标管理XML的部分数据为例database.xml

 
 1 <shapes name="mxGraph.aws.database">
2 <shape name="ElastiCache" h="56.81" w="55.7" aspect="variable" strokewidth="inherit">
3 <connections>
4 <constraint x="0.5" y="0" perimeter="0" name="N"/>
5 <constraint x="0.5" y="1" perimeter="0" name="S"/>
6 <constraint x="0" y="0.5" perimeter="0" name="W"/>
7 <constraint x="1" y="0.5" perimeter="0" name="E"/>
8 <constraint x="0.025" y="0.025" perimeter="0" name="NW"/>
9 <constraint x="0.025" y="0.975" perimeter="0" name="SW"/>
10 <constraint x="0.975" y="0.025" perimeter="0" name="NE"/>
11 <constraint x="0.975" y="0.975" perimeter="0" name="SE"/>
12 </connections>
13 <background>
14 <path>
15 <move x="0" y="51.81"/>
16 <curve x1="0" y1="54.57" x2="2.24" y2="56.81" x3="5" y3="56.81"/>
17 <line x="50.7" y="56.81"/>
18 <curve x1="53.46" y1="56.81" x2="55.7" y2="54.57" x3="55.7" y3="51.81"/>
19 <line x="55.7" y="5"/>
20 <curve x1="55.7" y1="2.24" x2="53.46" y2="0" x3="50.7" y3="0"/>
21 <line x="5" y="0"/>
22 <curve x1="2.24" y1="0" x2="0" y2="2.24" x3="0" y3="5"/>
23 <line x="0" y="51.81"/>
24 <close/>
25 </path>
26 </background>
27 <foreground>
28 <fillstroke/>
 

我写的这个SaveToXmlServlet.java文件的目的是将网络拓扑图保存至对应的XML文件中  以及  读取网络拓扑图对应的XML文件

 
 1 package grapheditor;
2 import java.io.BufferedReader;
3 import java.io.File;
4 import java.io.FileReader;
5 import java.io.IOException;
6 import java.io.PrintWriter;
7 import java.io.RandomAccessFile;
8 import javax.servlet.ServletException;
9 import javax.servlet.http.HttpServlet;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletResponse;
12 /**
13 * 将网络拓扑图保存至对应的XML文件中 以及 读取网络拓扑图对应的XML文件
14 * @author Visec·Dana
15 * @version V2.0 2014-7-17
16 */
17 public class SaveToXmlServlet extends HttpServlet {
18 private static final long serialVersionUID = 1L;
19 public void doGet(HttpServletRequest request, HttpServletResponse response)
20 throws ServletException, IOException {
21 this.doPost(request, response);
22 }
23 public void doPost(HttpServletRequest request, HttpServletResponse response)
24 throws ServletException, IOException {
25 response.setContentType("text/html;charset=utf-8");
26 response.setCharacterEncoding("utf-8");
27 request.setCharacterEncoding("utf-8");
28 String type = request.getParameter("type");
29 String tp = request.getParameter("tp");
30 StringBuffer result = new StringBuffer("");
31 String xmlPath=new String("");
32 String strPath = this.getClass().getResource("/").toString();
33 xmlPath = ("qsy".equals(tp))?"network_map/network_qsy.xml":("dzj".equals(tp))?"network_map/network_dzj.xml":("zdw".equals(tp))?"network_map/network_zdw.xml":"network_map/network_sp.xml";
34 String osName = System.getProperties().getProperty("os.name");
35 if(osName.toLowerCase().indexOf("windows")>-1){
36 strPath=strPath.substring(6)+xmlPath;
37 }else{
38 strPath=strPath.substring(5)+xmlPath;
39 }
40 File file = new File(strPath);
41 if(file.isFile()){//判断该路径是否为一个文件
42 if("set".equals(type.toLowerCase())){//文件保存
43 String xml = request.getParameter("xml");
44 if(xml==null||"".equals(xml)){
45 result.append("0");
46 }else{
47 RandomAccessFile randomAccessFile = new RandomAccessFile(strPath, "rw");
48 randomAccessFile.seek(0);
49 randomAccessFile.setLength(0);
50 randomAccessFile.write(xml.getBytes());
51 randomAccessFile.close();
52 result.append("1");
53 }
54 }else if("get".equals(type.toLowerCase())){//获取文件信息
55 //开始读取
56 BufferedReader reader = new BufferedReader(new FileReader(new File(strPath)));
57 String tempString = null;
58 // 一次读入一行,直到读入null为文件结束
59 while ((tempString = reader.readLine()) != null){
60 result.append(tempString);
61 }
62 reader.close();
63 }
64 }else{
65 System.out.println(strPath+" 找不到!");
66 result.append("0");
67 }
68
69 PrintWriter out = response.getWriter();
70 out.write(result.toString());
71 out.flush();
72 out.close();
73 }
74
75 }
 

当然这个文件的基础是先前有绘制好的拓扑图已经保存了相应的坐标位置和相应的数据

我编写network_qsy.xml是用来存储相应的坐标的临时文件

文件配置,以及不同项目之间的嵌入都不一样,所有就不详细介绍了,如感兴趣的朋友欢加入群一起探讨更多相关技术提高自身水平!

当然部分网友可能留意到

这里部分功能是没有完善的,能力有限,还需一些时间来琢磨!

当然后期的开发是无穷的,后期也在此基础上添加了右键绑定相关设备,合一拖动的形式配置相关信息,

参考资料:http://www.yworks.com/en/products_yed_about.html

http://docs.cryengine.com/display/SDKDOC2/Flow+Graph+Editor

http://www.univ-orleans.fr/lifo/software/Agape/javadoc/agape/applications/GraphEditor.html

上诉网站都是英文版的当时,也只是略看一些资料!

最新文章

  1. Scalaz(58)- scalaz-stream: fs2-并行运算示范,fs2 parallel processing
  2. c++左值和右值
  3. eval()与jQuery.parseJSON()的差别以及常见的解析缺少分号的问题
  4. EXTJS中的grid显示实际行号
  5. 类模板 template&lt;class T&gt;
  6. 其他函数:值为NULL时的默认值NVL,DECODE
  7. eclipse搭建elastic-job
  8. JavaScript(二)
  9. Hadoop Mapreduce运行流程
  10. 内核中的 ACCESS_ONCE()
  11. 把ajax包装成promise的形式(1)
  12. windows环境下命令打到服务中
  13. 配置CenOS网络,并用Xshell链接。
  14. 东师理想云平台异步任务处理系统V2.0重构思路
  15. 【转】WPF自定义控件与样式(3)-TextBox &amp; RichTextBox &amp; PasswordBox样式、水印、Label标签、功能扩展
  16. Java 持久化操作之 --XML
  17. leetcode 中等题(2)
  18. Unicode,GBK,GB2312,UTF-8概念基础(转载)
  19. ***在PHP语言中使用JSON和将json还原成数组(json_decode()的常见错误)
  20. 安装了XAMPP,PHP怎么显示中文

热门文章

  1. SpringBoot错误信息总结(不定时更新)
  2. 移动端 h5 开发相关内容总结——JavaScript 篇
  3. wireshark分析包中关于三次握手和四次终止标识
  4. Bootstrap相关优质项目学习清单
  5. 【26.8%】【CF 46D】Parking Lot
  6. 【10.58%】【codeforces 721C】Journey
  7. java并发api总结
  8. oracle员工表和部门表基本操作
  9. 小强的HTML5移动开发之路(53)——jQueryMobile页面间参数传递
  10. PEM_密钥对生成与读取方法