UNPKG

dagre-d3

Version:

A D3-based renderer for Dagre

424 lines (378 loc) 8.68 kB
<!doctype html> <meta charset="utf-8"> <title>Graph Storyboard. Add and Prune Dependencies Algorithm</title> <script src="https://d3js.org/d3.v4.js"></script> <script src="../dagre-d3.js"></script> <style id="css"> h1 { font-family: "Helvetica Neue", Helvetica, Arial, sans-serf; margin-top: 0.8em; margin-bottom: 0.2em; } text { font-weight: 300; font-family: "Helvetica Neue", Helvetica, Arial, sans-serf; font-size: 14px; } .node rect { stroke: #333; fill: #fff; stroke-width: 1.5px; } .node polygon { stroke: #333; fill: #fff; stroke-width: 1.5px; } .edgePath path.path { stroke: #333; fill: none; stroke-width: 1.5px; } div#top-frame { height: 350px; } div#WBS-frame { float: left; width: 50%; } div#dependencies-frame { float: left; width: 50%; } div#schedule-frame { float: none; } </style> <script> // Polyfill for PhantomJS. This can be safely ignored if not using PhantomJS. // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== 'function') { // closest thing possible to the ECMAScript 5 // internal IsCallable function throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() { return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; }; } </script> <script> var dagred3Story = function(svgelement, graphType, interframetime) { this.interframetime = interframetime; this.lastrenderTime = null; this.g = new dagreD3.graphlib.Graph().setGraph({}); //// Setup animation (if required) //this.g.graph().transition = function(selection) { // return selection.transition().duration(50); //}.bind(this); this.g.setDefaultEdgeLabel(function() { return {}; }); this.g.graph().marginx = 10; this.g.graph().marginy = 10; switch(graphType) { case 'Work Breakdown Structure': this.WBS = true; this.Schedule = false; this.g.graph().ranksep = 30; this.g.graph().nodesep = 30; break; case 'Schedule Network': this.Schedule = true; this.WBS = false; this.g.graph().rankdir = "LR"; this.g.graph().ranksep = 15; this.g.graph().nodesep = 15; break; default: console.log ("graphType of "+x+" is not implemented") } this.svg = d3.select(svgelement); this.inner = this.svg.append("g"); this.svg.call(d3.zoom().on("zoom", (function() { this.inner.attr("transform", d3.event.transform) }).bind(this))); this.t = 0; this.dagreD3render = new dagreD3.render(); }; dagred3Story.prototype.animateFrame = function(RenderAfter, Frame) { this.t += RenderAfter //var that = this; setTimeout(function() { Frame.forEach(function(x) { if (this.Schedule) { switch(x[0]) { case 'setActivity': this.g.setNode(x[1],{}) break; case 'removeNode': this.g.removeNode(x[1]) break; case 'setMilestone': this.g.setNode(x[1],{ shape: 'diamond', style: "fill: #fff; stroke: #000" }) break; case 'AddCoherenceEdge': this.g.setEdge(x[1], x[2], { curve: d3.curveBasis }); break; case 'AddDependencyEdge': this.g.setEdge(x[1], x[2], { curve: d3.curveBasis ,label: 'added' ,labeloffset: 5 ,labelpos: 'l' }); break; case 'MakeRedundantEdge': this.g.setEdge(x[1], x[2], { style: "stroke: #aaa; stroke-dasharray: 5, 10;" ,curve: d3.curveBasis ,arrowheadStyle: "fill: #aaa" ,labelpos: 'c' ,label: 'pruned' ,labelStyle: 'stroke: #aaa' }); break; case 'RemoveEdge': this.g.removeEdge(x[1], x[2]); break; default: console.log ("Schedule Network element "+x+" is not implemented") } } else if (this.WBS ) { switch(x[0]) { case 'setComponent': this.g.setNode(x[1],{}) break; case 'AddWBSEdge': this.g.setEdge(x[1], x[2], { arrowhead: 'undirected' }); break; default: console.log ("WBS element "+x+" is not implemented") } } }.bind(this)) if (this.g) { // Render this.dagreD3render(this.inner,this.g); } }.bind(this), this.t) }; dagred3Story.prototype.animateStory = function(RenderAfter, Story) { this.t += RenderAfter setTimeout(function() { Story.forEach(function(Frame) { this.animateFrame(this.interframetime, Frame); }.bind(this)) }.bind(this), this.t) }; </script> <div id="top-frame"> <div id="WBS-frame"> <h1>WBS</h1> <svg id="WBS" width=250 height=250></svg> </div> <div id="dependencies-frame"> <h1>Sequencing</h1> <svg id="dependencies" width=300 height=250></svg> </div> </div> <div id="schedule-frame"> <h1>Coherent Schedule Network</h1> <svg id="schedule" width=1150 height=500></svg> </div> <script id="js"> var framedelay = 2000; var dependenciesstory = new dagred3Story("#dependencies", "Schedule Network", framedelay); dependenciesstory.animateStory(0, [ [ ],[ ],[ ],[ ] ,[ ["setActivity", "A.1"] , ["setMilestone", "A.2 Start"] , ["AddDependencyEdge", "A.1", "A.2 Start"] ],[ ],[ ],[ ],[ ],[ ["setActivity", "A.2.2"] , ["setActivity", "A.2.3"] , ["AddDependencyEdge", "A.2.2", "A.2.3"] ],[ ],[ ],[ ],[ ],[ ["setActivity", "A.2.1"] , ["setActivity", "B"] , ["AddDependencyEdge", "A.2.1", "B"] ],[ ],[ ] ]); var WBSstory = new dagred3Story("#WBS", "Work Breakdown Structure", framedelay); WBSstory.animateStory(0, [ [ ["setComponent", "Project"] ],[ ["setComponent", "A"] , ["AddWBSEdge", "Project", "A"] , ["setComponent", "B"] , ["AddWBSEdge", "Project", "B"] ],[ ["setComponent", "A.1"] , ["AddWBSEdge", "A", "A.1"] , ["setComponent", "A.2"] , ["AddWBSEdge", "A", "A.2"] ],[ ["setComponent", "A.2.1"] , ["AddWBSEdge", "A.2", "A.2.1"] , ["setComponent", "A.2.2"] , ["AddWBSEdge", "A.2", "A.2.2"] , ["setComponent", "A.2.3"] , ["AddWBSEdge", "A.2", "A.2.3"] ] ]); var schedulestory = new dagred3Story("#schedule", "Schedule Network",framedelay); // Create the input graph schedulestory.animateStory(0, [ [ ["setActivity", "Project"] ],[ ["removeNode", "Project"] , ["setMilestone", "Project Finish"] , ["setMilestone", "Project Start"] , ["setActivity", "A"] , ["setActivity", "B"] , ["AddCoherenceEdge", "Project Start", "A"] , ["AddCoherenceEdge", "Project Start", "B"] , ["AddCoherenceEdge", "A", "Project Finish"] , ["AddCoherenceEdge", "B", "Project Finish"] ],[ ["removeNode", "A"] , ["setMilestone", "A Start"] , ["setActivity", "A.1"] , ["setActivity", "A.2"] , ["setMilestone", "A Finish"] , ["AddCoherenceEdge", "A Start", "A.1"] , ["AddCoherenceEdge", "A Start", "A.2"] , ["AddCoherenceEdge", "A.1", "A Finish"] , ["AddCoherenceEdge", "A.2", "A Finish"] , ["AddCoherenceEdge", "Project Start", "A Start"] , ["AddCoherenceEdge", "A Finish", "Project Finish"] ],[ ["removeNode", "A.2"] , ["setMilestone", "A.2 Start"] , ["setActivity", "A.2.1"] , ["setActivity", "A.2.2"] , ["setActivity", "A.2.3"] , ["setMilestone", "A.2 Finish"] , ["AddCoherenceEdge", "A.2 Start", "A.2.1"] , ["AddCoherenceEdge", "A.2 Start", "A.2.2"] , ["AddCoherenceEdge", "A.2 Start", "A.2.3"] , ["AddCoherenceEdge", "A.2.1", "A.2 Finish"] , ["AddCoherenceEdge", "A.2.2", "A.2 Finish"] , ["AddCoherenceEdge", "A.2.3", "A.2 Finish"] , ["AddCoherenceEdge", "A Start", "A.2 Start"] , ["AddCoherenceEdge", "A.2 Finish", "A Finish"] ] ,[ ["AddDependencyEdge", "A.1", "A.2 Start"] ],[ ["MakeRedundantEdge", "A Start", "A.2 Start"] ],[ ["MakeRedundantEdge", "A.1", "A Finish"] ],[ ["RemoveEdge", "A Start", "A.2 Start"] ],[ ["RemoveEdge", "A.1", "A Finish"] ],[ ["AddDependencyEdge", "A.2.2", "A.2.3"] ],[ ["MakeRedundantEdge", "A.2 Start", "A.2.3"] ],[ ["MakeRedundantEdge", "A.2.2", "A.2 Finish"] ],[ ["RemoveEdge", "A.2 Start", "A.2.3"] ],[ ["RemoveEdge", "A.2.2", "A.2 Finish"] ],[ ["AddDependencyEdge", "A.2.1", "B"] ],[ ["MakeRedundantEdge", "Project Start", "B"] ],[ ["RemoveEdge", "Project Start", "B"] ] ]); </script> </body> </html>