The management system developed by the company has the workflow graphic design and the view function, this function development history is relatively old. In that dark years, ie almost unified lake, so it is logical to use the smash hit of the VML technology.
Later things we all know, ie began to decline, VML this technology is now extinct, resulting in the original workflow graphics function can not be used completely, so the need to adopt new technology to rewrite the workflow graphical function.
After the comparison, decided to use the Zrender Library to implement (about the Zrender library introduction, see http://ecomfe.github.io/zrender/), took a day, and finally made a general effect model, as shown:
The flowchart consists of two types of parts: moving parts and connected arc parts, each of which contains multiple parts with different traits.
Take the active part as an example, the circle is the start activity, the parallelogram is the automatic activity, the rectangle is the artificial activity, and so on.
On the code implementation, the unit (part base class) is defined, and all parts inherit from this base class. The graph class manages the entire flowchart, including all parts, context menus, and so on, which are managed and dispatched uniformly by graph, with the following code:
var Libra = {}; Libra.workflow = {}; Libra.Workflow.Graph = function (type, options) {var Graph = this, activities = {}, transitions = {}; var zrenderinstance, Contextmenucontainer; This.type = type; this.addactivity = function (activity) {activity.graph = graph; Activities[activity.id] = {object:activity}; }; This.getactivity = function (ID) {return activities[id].object;}; this.addtransition = function (transition) {transition.graph = graph; Transitions[transition.id] = {object:transition}; }; function modelements (shapes) {Shapes.each (shape) {zrenderinstance.modelement (shape);}); return shapes; }//The node currently being dragged is var dragingactivity = null; Active node drag and drop Start This.onactivitydragstart = function (activity) {dragingactivity = activity;}; Active node drag-and-drop end this.onactivitydragend = function () {if (dragingactivity) refreshactivitytransitions (dragingactivity) ; Dragingactivity = nUll }; The drag process handles function Zrenderinstanceonmousemove () {if (dragingactivity! = null) refreshactivitytransitions (Draginga ctivity); }//Refresh activity related to all connections arc function refreshactivitytransitions (activity) {var ActivityID = activity.id; for (var key in transitions) {var transition = Transitions[key].object; if (Transition.from = = = ActivityID | | transition.to = = ActivityID) {zrenderinstance.refreshshapes (modElement S (Transition.refresh (graph))); }}}//The currently selected part var selectedunit = null; This.onunitselect = function (unit) {if (selectedunit) zrenderinstance.refreshshapes (modelements (Selectedunit.unsele CT (graph)); Zrenderinstance.refreshshapes (Modelements (unit.select (graph)); Selectedunit = unit; }; Records the current mouse on which part, can be used to generate context-sensitive menu var currentunit = null; This.onunitmouseover = function (unit) {currentunit = unit; }; This.onunitmouseout = function (unit) { if (currentunit = = = Unit) Currentunit = NULL; }; Context Menu Event response function OnContextMenu (event) {event.stop (event); if (currentunit) Currentunit.showcontextmenu (event, Contextmenucontainer, graph); } This.addshape = function (Shape) {zrenderinstance.addshape (shape); }; Initialize this.init = function () {var canvaselement = options.canvas.element; Canvaselement.empty (); Canvaselement.setstyle ({height:document.viewport.getHeight () + ' px '}); Zrenderinstance = Graph.type.zrender.init (document.getElementById (Canvaselement.identify ())); for (var key in activities) {activities[key].object.addto (graph);} for (var key in transitions) {transitions[key].object.addto (graph);} Create context menu Container Contextmenucontainer = new Element (' div ', {' class ': ' Context-menu '}); Contextmenucontainer.hide (); Document.body.appendChild (Contextmenucontainer); Event.observe (Contextmenucontainer, ' mouseout ', FuNction (Event) {//close, you should determine if the mouse has moved out of the menu container if (! Position.within (Contextmenucontainer, Event.clientx, Event.clienty)) {contextmenucontainer.hide (); } }); Listen for the drag process zrenderinstance.on (' MouseMove ', zrenderinstanceonmousemove); Context menu Event.observe (document, ' ContextMenu ', oncontextmenu); }; Renders or refreshes rendering This.render = function () {var canvaselement = options.canvas.element; Canvaselement.setstyle ({height:document.viewport.getHeight () + ' px '}); Zrenderinstance.render (); };};/ * * Components (including active and connected arcs) */libra.workflow.unit = Class.create ({id:null, title:null, Graph:null,//currently selected Sele Cted:false,//context menu item collection Contextmenuitems: [], Initialize:function (options) {var _this = this; _this.id = options.id; _this.title = Options.title; }, Createshapeoptions:function () {var _this = this; return {HoVerable:true, Clickable:true, onclick:function (params) {//Select and Highlight _this.graph.onunitselect (_this); }, Onmouseover:function (params) {_this.graph.onunitmouseover (_this);}, Onmouseout:function (params ) {_this.graph.onunitmouseout (_this);} }; }, Addto:function (graph) {},//Refresh display Refresh:function (graph) {return [];},//select Select:function (graph) { This.selected = true; return This.refresh (graph); },//uncheck Unselect:function (graph) {this.selected = false; return This.refresh (graph); },//Display context menu Showcontextmenu:function (event, container, graph) {container.hide (); container.innerhtml = "; var ul = new Element (' ul '); Container.appendchild (UL); This.buildcontextmenuitems (UL, graph); Add offset, so that the mouse is in the menu var =-5; var rightedge = Document.body.clientwidth-event.clientx;var Bottomedge = document.body.clientheight-event.clienty;if (Rightedge < Container.offsetwidth) Container.style.left = document.body.scrollLeft + event.clientx-container.offsetwidth + offset; Elsecontainer.style.left = document.body.scrollLeft + Event.clientx + offset;if (Bottomedge < Container.offsetheight ) Container.style.top = document.body.scrollTop + event.clienty-container.offsetheight + offset; Elsecontainer.style.top = document.body.scrollTop + event.clienty + offset; Container.show (); },//Create context menu item buildcontextmenuitems:function (container, graph) {var unit = this; Unit.contextMenuItems.each (function (item) {Item.addto (container); }); }});
Zrender the drag of the drawing is supported by default, so the drag of the moving part only needs to set the Dragable property to True. However, although the active part can be dragged, the connectors on the active part do not move together, which requires a real-time redraw of the connector by listening for drag-start events, drag-end events, and mouse movement events during drag. Listening for mouse movement events in graph is for real-time redrawing of related graphics such as connection lines.
Each part has eight connection points planned, and by default the connection arc is not fixed to a connection point, but the nearest connection point is automatically found based on the position of the active part, so when you drag the moving part, you can see that the connection point on the active part is constantly changing.
The above is just the simplest way to achieve the basic functions of graphical design of the workflow, the perfect graphical design should include curves, connection points drag and drop, and so on, as shown in:
The above is the company's products in the workflow graphical design function, the function of the above example to improve a lot, but the basic principle is not changed, nothing more than the details of processing more.
Especially in the painting of the place spent a lot of time, middle school plane geometry knowledge almost forgotten, so it took a lot of effort, this part is prepared to write a special article to elaborate.
The end of this article will give the previous modeling test phase of the complete code download, is the early code, not the final code, the reason you understand, forgive me.
Http://files.cnblogs.com/files/rrooyy/WorkflowGraphic.zip
Graphical design of Workflow with Zrender (sample code included)