做工作流需要用到mxgraph绘制流程图,但是mxgraph在国内资料 ,不得不研究官方API和例子,一点一点摸清楚。
首先,在官网下载资源包mxgraph-master,讲部分核心文件导入到工程里面,如下图:
第二步,初始化容器,实现图形绘制、图形删除、、xml预览、xml保存、xml读取,全部JS代码如下,部分后台自己实现。
<script type="text/javascript">
mxBasePath = '../';
</script>
<!-- Loads and initializes the library -->
<script type="text/javascript" src="js/mxClient.js"></script>
<script type="text/javascript" src="js/jquery-1.8.2.js"></script>
<!-- Example code -->
<script type="text/javascript">
function mxVertexToolHandler(state)
{
mxVertexHandler.apply(this, arguments);
};
mxVertexToolHandler.prototype = new mxVertexHandler();
mxVertexToolHandler.prototype.constructor = mxVertexToolHandler;
mxVertexToolHandler.prototype.domNode = null;
mxVertexToolHandler.prototype.init = function()
{
mxVertexHandler.prototype.init.apply(this, arguments);
// In this example we force the use of DIVs for images in IE. This
// handles transparency in PNG images properly in IE and fixes the
// problem that IE routes all mouse events for a gesture via the
// initial IMG node, which means the target vertices
this.domNode = document.createElement('div');
this.domNode.style.position = 'absolute';
this.domNode.style.whiteSpace = 'nowrap';
var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
// Delete
var img = mxUtils.createImage('images/delete2.png');
img.style.cursor = 'pointer';
img.style.width = '16px';
img.style.height = '16px';
mxEvent.addListener(img, md,
mxUtils.bind(this, function(evt)
{
// Disables dragging the image
mxEvent.consume(evt);
})
);
mxEvent.addListener(img, 'click',
mxUtils.bind(this, function(evt)
{
this.graph.removeCells([this.state.cell]);
mxEvent.consume(evt);
})
);
this.domNode.appendChild(img);
this.graph.container.appendChild(this.domNode);
this.redrawTools();
};
mxVertexToolHandler.prototype.redraw = function()
{
mxVertexHandler.prototype.redraw.apply(this);
this.redrawTools();
};
mxVertexToolHandler.prototype.redrawTools = function()
{
if (this.state != null && this.domNode != null)
{
var dy = (mxClient.IS_VML && document.compatMode == 'CSS1Compat') ? 20 : 4;
this.domNode.style.left = (this.state.x + this.state.width - 56) + 'px';
this.domNode.style.top = (this.state.y + this.state.height + dy) + 'px';
}
};
mxVertexToolHandler.prototype.destroy = function(sender, me)
{
mxVertexHandler.prototype.destroy.apply(this, arguments);
if (this.domNode != null)
{
this.domNode.parentNode.removeChild(this.domNode);
this.domNode = null;
}
};
// Program starts here. Creates a sample graph in the
// DOM node with the specified ID. This function is invoked
// from the onLoad event handler of the document (see below).
function main()
{
// Checks if browser is supported
if (!mxClient.isBrowserSupported())
{
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
}
else
{
//图形之间连线的样式图
mxConnectionHandler.prototype.connectImage = new mxImage('images/connector.gif', 16, 16);
// 创建工具栏容器
var tbContainer = document.createElement('div');
tbContainer.style.position = 'absolute';
tbContainer.style.overflow = 'hidden';
tbContainer.style.padding = '2px';
tbContainer.style.left = '0px';
tbContainer.style.top = '50px';
tbContainer.style.width = '24px';
tbContainer.style.bottom = '0px';
document.body.appendChild(tbContainer);
// Workaround for Internet Explorer ignoring certain styles
if (mxClient.IS_IE)
{
new mxDivResizer(tbContainer);
}
// Creates new toolbar without event processing
var toolbar = new mxToolbar(tbContainer);
toolbar.enabled = false
// 创建graph容器
var container = document.createElement('div');
container.style.position = 'absolute';
container.style.overflow = 'hidden';
container.style.left = '24px';
container.style.top = '50px';
container.style.right = '0px';
container.style.bottom = '0px';
container.style.background = 'url("images/grid.gif")';
document.body.appendChild(container);
// Workaround for Internet Explorer ignoring certain styles
if (mxClient.IS_IE)
{
new mxDivResizer(container);
}
//实例化graph
var model = new mxGraphModel();
var graph = new mxGraph(container, model);
//读取本地xml文件显示图形
//graph.getModel().beginUpdate();
try
{
// Loads the custom file format (TXT file)
//parse(graph, 'fileio.txt');
// Loads the mxGraph file format (XML file)
read(graph, 'xml/save.xml');
}
finally
{
// Updates the display
//graph.getModel().endUpdate();
}
//删除图形
graph.createHandler = function(state)
{
if (state != null &&
this.model.isVertex(state.cell))
{
return new mxVertexToolHandler(state);
}
return mxGraph.prototype.createHandler.apply(this, arguments);
};
//xml预览
document.body.appendChild(mxUtils.button('View XML', function()
{
var encoder = new mxCodec();
var node = encoder.encode(graph.getModel());
console.log(mxUtils.getPrettyXml(node));
mxUtils.popup(mxUtils.getPrettyXml(node), true);
}));
//保存xml
document.body.appendChild(mxUtils.button('Save XML', function()
{
var encoder = new mxCodec();
var node = encoder.encode(graph.getModel());
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/SaveServlet",
cache:false,
data:{
xml:mxUtils.getPrettyXml(node)
},
success:function(data){
alert(data);
}
});
}));
// Enables new connections in the graph
graph.setConnectable(true);
graph.setMultigraph(false);
// Stops editing on enter or escape keypress
var keyHandler = new mxKeyHandler(graph);
var rubberband = new mxRubberband(graph);
var addVertex = function(icon, w, h, style)
{
var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
vertex.setVertex(true);
var img = addToolbarItem(graph, toolbar, vertex, icon);
img.enabled = true;
graph.getSelectionModel().addListener(mxEvent.CHANGE, function()
{
var tmp = graph.isSelectionEmpty();
mxUtils.setOpacity(img, (tmp) ? 100 : 20);
img.enabled = tmp;
});
};
//工具栏区域的图形
addVertex('images/rectangle.gif', 100, 40, '');
addVertex('images/rounded.gif', 100, 40, 'shape=rounded');
addVertex('images/ellipse.gif', 40, 40, 'shape=ellipse');
addVertex('images/rhombus.gif', 40, 40, 'shape=rhombus');
addVertex('images/triangle.gif', 40, 40, 'shape=triangle');
addVertex('images/cylinder.gif', 40, 40, 'shape=cylinder');
addVertex('images/actor.gif', 30, 40, 'shape=actor');
}
}
function addToolbarItem(graph, toolbar, prototype, image)
{
// Function that is executed when the image is dropped on
// the graph. The cell argument points to the cell under
// the mousepointer if there is one.
var funct = function(graph, evt, cell, x, y)
{
graph.stopEditing(false);
var vertex = graph.getModel().cloneCell(prototype);
vertex.geometry.x = x;
vertex.geometry.y = y;
graph.addCell(vertex);
graph.setSelectionCell(vertex);
}
// Creates the image which is used as the drag icon (preview)
var img = toolbar.addMode(null, image, function(evt, cell)
{
var pt = this.graph.getPointForEvent(evt);
funct(graph, evt, cell, pt.x, pt.y);
});
// Disables dragging if element is disabled. This is a workaround
// for wrong event order in IE. Following is a dummy listener that
// is invoked as the last listener in IE.
mxEvent.addListener(img, 'mousedown', function(evt)
{
// do nothing
});
// This listener is always called first before any other listener
// in all browsers.
mxEvent.addListener(img, 'mousedown', function(evt)
{
if (img.enabled == false)
{
mxEvent.consume(evt);
}
});
mxUtils.makeDraggable(img, graph, funct);
return img;
}
// Parses the mxGraph XML file format
function read(graph, filename)
{
var req = mxUtils.load(filename);
var root = req.getDocumentElement();
var dec = new mxCodec(root.ownerDocument);
dec.decode(root, graph.getModel());
};
</script>
最终页面效果如下: