graph-story-board.html 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <!doctype html>
  2. <meta charset="utf-8">
  3. <title>Graph Storyboard. Add and Prune Dependencies Algorithm</title>
  4. <script src="../../node_modules/graphlibrary/dist/graphlib.js"></script>
  5. <script src="../../node_modules/d3/build/d3.js"></script>
  6. <script src="../dagre-d3.js"></script>
  7. <style id="css">
  8. h1 {
  9. font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
  10. margin-top: 0.8em;
  11. margin-bottom: 0.2em;
  12. }
  13. text {
  14. font-weight: 300;
  15. font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
  16. font-size: 14px;
  17. }
  18. .node rect {
  19. stroke: #333;
  20. fill: #fff;
  21. stroke-width: 1.5px;
  22. }
  23. .node polygon {
  24. stroke: #333;
  25. fill: #fff;
  26. stroke-width: 1.5px;
  27. }
  28. .edgePath path.path {
  29. stroke: #333;
  30. fill: none;
  31. stroke-width: 1.5px;
  32. }
  33. div#top-frame {
  34. height: 350px;
  35. }
  36. div#WBS-frame {
  37. float: left;
  38. width: 50%;
  39. }
  40. div#dependencies-frame {
  41. float: left;
  42. width: 50%;
  43. }
  44. div#schedule-frame {
  45. float: none;
  46. }
  47. </style>
  48. <script>
  49. // Polyfill for PhantomJS. This can be safely ignored if not using PhantomJS.
  50. // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
  51. if (!Function.prototype.bind) {
  52. Function.prototype.bind = function(oThis) {
  53. if (typeof this !== 'function') {
  54. // closest thing possible to the ECMAScript 5
  55. // internal IsCallable function
  56. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  57. }
  58. var aArgs = Array.prototype.slice.call(arguments, 1),
  59. fToBind = this,
  60. fNOP = function() {},
  61. fBound = function() {
  62. return fToBind.apply(this instanceof fNOP && oThis
  63. ? this
  64. : oThis,
  65. aArgs.concat(Array.prototype.slice.call(arguments)));
  66. };
  67. fNOP.prototype = this.prototype;
  68. fBound.prototype = new fNOP();
  69. return fBound;
  70. };
  71. }
  72. </script>
  73. <script>
  74. var dagred3Story = function(svgelement, graphType, interframetime) {
  75. this.interframetime = interframetime;
  76. this.lastrenderTime = null;
  77. this.g = new graphlib.Graph().setGraph({});
  78. //// Setup animation (if required)
  79. //this.g.graph().transition = function(selection) {
  80. // return selection.transition().duration(50);
  81. //}.bind(this);
  82. this.g.setDefaultEdgeLabel(function() { return {}; });
  83. this.g.graph().marginx = 10;
  84. this.g.graph().marginy = 10;
  85. switch(graphType) {
  86. case 'Work Breakdown Structure':
  87. this.WBS = true;
  88. this.Schedule = false;
  89. this.g.graph().ranksep = 30;
  90. this.g.graph().nodesep = 30;
  91. break;
  92. case 'Schedule Network':
  93. this.Schedule = true;
  94. this.WBS = false;
  95. this.g.graph().rankdir = "LR";
  96. this.g.graph().ranksep = 15;
  97. this.g.graph().nodesep = 15;
  98. break;
  99. default:
  100. console.log ("graphType of "+x+" is not implemented")
  101. }
  102. this.svg = d3.select(svgelement);
  103. this.inner = this.svg.append("g");
  104. this.svg.call(d3.zoom().on("zoom", (function() {
  105. this.inner.attr("transform", d3.event.transform)
  106. }).bind(this)));
  107. this.t = 0;
  108. this.dagreD3render = new dagreD3.render();
  109. };
  110. dagred3Story.prototype.animateFrame = function(RenderAfter, Frame) {
  111. this.t += RenderAfter
  112. //var that = this;
  113. setTimeout(function() {
  114. Frame.forEach(function(x) {
  115. if (this.Schedule) {
  116. switch(x[0]) {
  117. case 'setActivity':
  118. this.g.setNode(x[1],{})
  119. break;
  120. case 'removeNode':
  121. this.g.removeNode(x[1])
  122. break;
  123. case 'setMilestone':
  124. this.g.setNode(x[1],{ shape: 'diamond', style: "fill: #fff; stroke: #000" })
  125. break;
  126. case 'AddCoherenceEdge':
  127. this.g.setEdge(x[1], x[2], {
  128. curve: d3.curveBasis
  129. });
  130. break;
  131. case 'AddDependencyEdge':
  132. this.g.setEdge(x[1], x[2], {
  133. curve: d3.curveBasis
  134. ,label: 'added'
  135. ,labeloffset: 5
  136. ,labelpos: 'l'
  137. });
  138. break;
  139. case 'MakeRedundantEdge':
  140. this.g.setEdge(x[1], x[2], {
  141. style: "stroke: #aaa; stroke-dasharray: 5, 10;"
  142. ,curve: d3.curveBasis
  143. ,arrowheadStyle: "fill: #aaa"
  144. ,labelpos: 'c'
  145. ,label: 'pruned'
  146. ,labelStyle: 'stroke: #aaa'
  147. });
  148. break;
  149. case 'RemoveEdge':
  150. this.g.removeEdge(x[1], x[2]);
  151. break;
  152. default:
  153. console.log ("Schedule Network element "+x+" is not implemented")
  154. }
  155. } else if (this.WBS ) {
  156. switch(x[0]) {
  157. case 'setComponent':
  158. this.g.setNode(x[1],{})
  159. break;
  160. case 'AddWBSEdge':
  161. this.g.setEdge(x[1], x[2], {
  162. arrowhead: 'undirected'
  163. });
  164. break;
  165. default:
  166. console.log ("WBS element "+x+" is not implemented")
  167. }
  168. }
  169. }.bind(this))
  170. if (this.g) {
  171. // Render
  172. this.dagreD3render(this.inner,this.g);
  173. }
  174. }.bind(this), this.t)
  175. };
  176. dagred3Story.prototype.animateStory = function(RenderAfter, Story) {
  177. this.t += RenderAfter
  178. setTimeout(function() {
  179. Story.forEach(function(Frame) {
  180. this.animateFrame(this.interframetime, Frame);
  181. }.bind(this))
  182. }.bind(this), this.t)
  183. };
  184. </script>
  185. <div id="top-frame">
  186. <div id="WBS-frame">
  187. <h1>WBS</h1>
  188. <svg id="WBS" width=250 height=250></svg>
  189. </div>
  190. <div id="dependencies-frame">
  191. <h1>Sequencing</h1>
  192. <svg id="dependencies" width=300 height=250></svg>
  193. </div>
  194. </div>
  195. <div id="schedule-frame">
  196. <h1>Coherent Schedule Network</h1>
  197. <svg id="schedule" width=1150 height=500></svg>
  198. </div>
  199. <script id="js">
  200. var framedelay = 2000;
  201. var dependenciesstory = new dagred3Story("#dependencies", "Schedule Network", framedelay);
  202. dependenciesstory.animateStory(0,
  203. [
  204. [
  205. ],[
  206. ],[
  207. ],[
  208. ]
  209. ,[
  210. ["setActivity", "A.1"]
  211. ,
  212. ["setMilestone", "A.2 Start"]
  213. ,
  214. ["AddDependencyEdge", "A.1", "A.2 Start"]
  215. ],[
  216. ],[
  217. ],[
  218. ],[
  219. ],[
  220. ["setActivity", "A.2.2"]
  221. ,
  222. ["setActivity", "A.2.3"]
  223. ,
  224. ["AddDependencyEdge", "A.2.2", "A.2.3"]
  225. ],[
  226. ],[
  227. ],[
  228. ],[
  229. ],[
  230. ["setActivity", "A.2.1"]
  231. ,
  232. ["setActivity", "B"]
  233. ,
  234. ["AddDependencyEdge", "A.2.1", "B"]
  235. ],[
  236. ],[
  237. ]
  238. ]);
  239. var WBSstory = new dagred3Story("#WBS", "Work Breakdown Structure", framedelay);
  240. WBSstory.animateStory(0,
  241. [
  242. [
  243. ["setComponent", "Project"]
  244. ],[
  245. ["setComponent", "A"]
  246. ,
  247. ["AddWBSEdge", "Project", "A"]
  248. ,
  249. ["setComponent", "B"]
  250. ,
  251. ["AddWBSEdge", "Project", "B"]
  252. ],[
  253. ["setComponent", "A.1"]
  254. ,
  255. ["AddWBSEdge", "A", "A.1"]
  256. ,
  257. ["setComponent", "A.2"]
  258. ,
  259. ["AddWBSEdge", "A", "A.2"]
  260. ],[
  261. ["setComponent", "A.2.1"]
  262. ,
  263. ["AddWBSEdge", "A.2", "A.2.1"]
  264. ,
  265. ["setComponent", "A.2.2"]
  266. ,
  267. ["AddWBSEdge", "A.2", "A.2.2"]
  268. ,
  269. ["setComponent", "A.2.3"]
  270. ,
  271. ["AddWBSEdge", "A.2", "A.2.3"]
  272. ]
  273. ]);
  274. var schedulestory = new dagred3Story("#schedule", "Schedule Network",framedelay);
  275. // Create the input graph
  276. schedulestory.animateStory(0,
  277. [
  278. [
  279. ["setActivity", "Project"]
  280. ],[
  281. ["removeNode", "Project"]
  282. ,
  283. ["setMilestone", "Project Finish"]
  284. ,
  285. ["setMilestone", "Project Start"]
  286. ,
  287. ["setActivity", "A"]
  288. ,
  289. ["setActivity", "B"]
  290. ,
  291. ["AddCoherenceEdge", "Project Start", "A"]
  292. ,
  293. ["AddCoherenceEdge", "Project Start", "B"]
  294. ,
  295. ["AddCoherenceEdge", "A", "Project Finish"]
  296. ,
  297. ["AddCoherenceEdge", "B", "Project Finish"]
  298. ],[
  299. ["removeNode", "A"]
  300. ,
  301. ["setMilestone", "A Start"]
  302. ,
  303. ["setActivity", "A.1"]
  304. ,
  305. ["setActivity", "A.2"]
  306. ,
  307. ["setMilestone", "A Finish"]
  308. ,
  309. ["AddCoherenceEdge", "A Start", "A.1"]
  310. ,
  311. ["AddCoherenceEdge", "A Start", "A.2"]
  312. ,
  313. ["AddCoherenceEdge", "A.1", "A Finish"]
  314. ,
  315. ["AddCoherenceEdge", "A.2", "A Finish"]
  316. ,
  317. ["AddCoherenceEdge", "Project Start", "A Start"]
  318. ,
  319. ["AddCoherenceEdge", "A Finish", "Project Finish"]
  320. ],[
  321. ["removeNode", "A.2"]
  322. ,
  323. ["setMilestone", "A.2 Start"]
  324. ,
  325. ["setActivity", "A.2.1"]
  326. ,
  327. ["setActivity", "A.2.2"]
  328. ,
  329. ["setActivity", "A.2.3"]
  330. ,
  331. ["setMilestone", "A.2 Finish"]
  332. ,
  333. ["AddCoherenceEdge", "A.2 Start", "A.2.1"]
  334. ,
  335. ["AddCoherenceEdge", "A.2 Start", "A.2.2"]
  336. ,
  337. ["AddCoherenceEdge", "A.2 Start", "A.2.3"]
  338. ,
  339. ["AddCoherenceEdge", "A.2.1", "A.2 Finish"]
  340. ,
  341. ["AddCoherenceEdge", "A.2.2", "A.2 Finish"]
  342. ,
  343. ["AddCoherenceEdge", "A.2.3", "A.2 Finish"]
  344. ,
  345. ["AddCoherenceEdge", "A Start", "A.2 Start"]
  346. ,
  347. ["AddCoherenceEdge", "A.2 Finish", "A Finish"]
  348. ]
  349. ,[
  350. ["AddDependencyEdge", "A.1", "A.2 Start"]
  351. ],[
  352. ["MakeRedundantEdge", "A Start", "A.2 Start"]
  353. ],[
  354. ["MakeRedundantEdge", "A.1", "A Finish"]
  355. ],[
  356. ["RemoveEdge", "A Start", "A.2 Start"]
  357. ],[
  358. ["RemoveEdge", "A.1", "A Finish"]
  359. ],[
  360. ["AddDependencyEdge", "A.2.2", "A.2.3"]
  361. ],[
  362. ["MakeRedundantEdge", "A.2 Start", "A.2.3"]
  363. ],[
  364. ["MakeRedundantEdge", "A.2.2", "A.2 Finish"]
  365. ],[
  366. ["RemoveEdge", "A.2 Start", "A.2.3"]
  367. ],[
  368. ["RemoveEdge", "A.2.2", "A.2 Finish"]
  369. ],[
  370. ["AddDependencyEdge", "A.2.1", "B"]
  371. ],[
  372. ["MakeRedundantEdge", "Project Start", "B"]
  373. ],[
  374. ["RemoveEdge", "Project Start", "B"]
  375. ]
  376. ]);
  377. </script>
  378. </body>
  379. </html>