blob: 88d1388b77becb55bf68a4d6eb5c817663265db9 [file] [log] [blame]
Matteo Scandolobe9b13d2016-01-21 11:21:03 -08001(function () {
2 'use strict';
3
4 angular.module('xos.serviceTopology')
5 .directive('serviceCanvas', function(){
6 return {
7 restrict: 'E',
8 scope: {},
9 bindToController: true,
10 controllerAs: 'vm',
11 templateUrl: 'templates/topology_canvas.tpl.html',
12 controller: function($element, $window, d3, serviceTopologyConfig){
13
14 // count the mas depth of an object
15 const depthOf = (obj) => {
16 var depth = 0;
17 if (obj.children) {
18 obj.children.forEach(function (d) {
19 var tmpDepth = depthOf(d);
20 if (tmpDepth > depth) {
21 depth = tmpDepth
22 }
23 })
24 }
25 return 1 + depth
26 };
27
28 const treeData = [
29 {
30 'name': 'Top Level',
31 'parent': 'null',
32 'children': [
33 {
34 'name': 'Level 2: A',
35 'parent': 'Top Level',
36 'children': [
37 {
38 'name': 'Son of A',
39 'parent': 'Level 2: A'
40 },
41 {
42 'name': 'Daughter of A',
43 'parent': 'Level 2: A'
44 }
45 ]
46 },
47 {
48 'name': 'Level 2: B',
49 'parent': 'Top Level'
50 }
51 ]
52 }
53 ];
54
55 const width = $window.innerWidth - serviceTopologyConfig.widthMargin;
56 const height = $window.innerHeight - serviceTopologyConfig.heightMargin;
57
58 const tree = d3.layout.tree()
59 .size([height, width]);
60
61 const diagonal = d3.svg.diagonal()
62 .projection(d => [d.y, d.x]);
63
64 const svg = d3.select($element[0])
65 .append('svg')
66 .style('width', `${$window.innerWidth}px`)
67 .style('height', `${$window.innerHeight}px`)
68 .append('g')
69 .attr("transform", "translate(" + serviceTopologyConfig.widthMargin+ "," + serviceTopologyConfig.heightMargin + ")");;
70
71 const resizeCanvas = () => {
72 var targetSize = svg.node().getBoundingClientRect();
73
74 d3.select(self.frameElement)
75 .attr('width', `${targetSize.width}px`)
76 .attr('height', `${targetSize.height}px`)
77 };
78
79 //d3.select(window)
80 // .on('load', () => {
81 // resizeCanvas();
82 // });
83 //d3.select(window)
84 // .on('resize', () => {
85 // resizeCanvas();
86 // update(root);
87 // });
88
89 var root = treeData[0];
90 root.x0 = $window.innerHeight / 2;
91 root.y0 = 0;
92
93 var i = 0;
94 var duration = 750;
95
96 update(root);
97
98 function update(source) {
99
100 const maxDepth = depthOf(source);
101
102 // Compute the new tree layout.
103 var nodes = tree.nodes(root).reverse(),
104 links = tree.links(nodes);
105
106 // Normalize for fixed-depth.
107 nodes.forEach(function(d) {
108 console.log(d);
109 // 180 should be based on window.width and max node depth
110
111 d.y = d.depth * (($window.innerWidth - (serviceTopologyConfig.widthMargin * 2)) / maxDepth);
112 console.log(d.x);
113 });
114
115 // Update the nodes…
116 var node = svg.selectAll('g.node')
117 .data(nodes, function(d) { return d.id || (d.id = ++i); });
118
119 // Enter any new nodes at the parent's previous position.
120 var nodeEnter = node.enter().append('g')
121 .attr('class', 'node')
122 .attr('transform', function(d) {
123 // this is the starting position
124 return 'translate(' + source.y0 + ',' + source.x0 + ')';
125 });
126 //.on('click', click);
127
128 nodeEnter.append('circle')
129 .attr('r', 1e-6)
130 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
131
132 nodeEnter.append('text')
133 .attr('x', function(d) { return d.children || d._children ? -13 : 13; })
134 .attr('dy', '.35em')
135 .attr('text-anchor', function(d) { return d.children || d._children ? 'end' : 'start'; })
136 .text(function(d) { return d.name; })
137 .style('fill-opacity', 1e-6);
138
139 // Transition nodes to their new position.
140 var nodeUpdate = node.transition()
141 .duration(duration)
142 .attr('transform', function(d) {
143 return 'translate(' + d.y + ',' + d.x + ')';
144 });
145
146 nodeUpdate.select('circle')
147 .attr('r', 10)
148 .style('fill', function(d) { return d._children ? 'lightsteelblue' : '#fff'; });
149
150 nodeUpdate.select('text')
151 .style('fill-opacity', 1);
152
153 // Transition exiting nodes to the parent's new position.
154 var nodeExit = node.exit().transition()
155 .duration(duration)
156 .attr('transform', function(d) { return 'translate(' + source.y + ',' + source.x + ')'; })
157 .remove();
158
159 nodeExit.select('circle')
160 .attr('r', 1e-6);
161
162 nodeExit.select('text')
163 .style('fill-opacity', 1e-6);
164
165 // Update the links…
166 var link = svg.selectAll('path.link')
167 .data(links, function(d) { return d.target.id; });
168
169 // Enter any new links at the parent's previous position.
170 link.enter().insert('path', 'g')
171 .attr('class', 'link')
172 .attr('d', function(d) {
173 var o = {x: source.x0, y: source.y0};
174 return diagonal({source: o, target: o});
175 });
176
177 // Transition links to their new position.
178 link.transition()
179 .duration(duration)
180 .attr('d', diagonal);
181
182 // Transition exiting nodes to the parent's new position.
183 link.exit().transition()
184 .duration(duration)
185 .attr('d', function(d) {
186 var o = {x: source.x, y: source.y};
187 return diagonal({source: o, target: o});
188 })
189 .remove();
190
191 // Stash the old positions for transition.
192 nodes.forEach(function(d) {
193 d.x0 = d.x;
194 d.y0 = d.y;
195 });
196 }
197 }
198 }
199 });
200
201}());