forked from NorthwoodsSoftware/GoJS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathradialPartition.html
209 lines (191 loc) · 8.87 KB
/
radialPartition.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Radial Partition Layout</title>
<meta name="description" content="Arrange people in rings around a central person, in layers according to distance from the central person." />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Copyright 1998-2019 by Northwoods Software Corporation. -->
<script src="../release/go.js"></script>
<script src="../extensions/RadialLayout.js"></script>
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
<script id="code">
var layerThickness = 70; // how thick each ring should be
function init() {
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
var $ = go.GraphObject.make; // for conciseness in defining templates
myDiagram =
$(go.Diagram, "myDiagramDiv", // must be the ID or reference to div
{
initialAutoScale: go.Diagram.Uniform,
isReadOnly: true,
maxSelectionCount: 1,
layout: $(RadialLayout, {
maxLayers: 5,
layerThickness: layerThickness,
rotateNode: function(node, angle, sweep, radius) {
// all nodes are centered at the origin
node.location = this.arrangementOrigin;
// because the Shape.geometry will be centered at the origin --
// see makeAnnularWedge, below
node.diagram.model.setDataProperty(node.data, "angle", angle);
node.diagram.model.setDataProperty(node.data, "sweep", sweep);
node.diagram.model.setDataProperty(node.data, "radius", radius);
}
}),
"animationManager.isEnabled": false
});
var commonToolTip =
$("ToolTip",
$(go.Panel, "Vertical",
{ margin: 3 },
$(go.TextBlock, // bound to node data
{ margin: 4, font: "bold 12pt sans-serif" },
new go.Binding("text")),
$(go.TextBlock, // bound to node data
new go.Binding("text", "color", function(c) { return "Color: " + c; })),
$(go.TextBlock, // bound to Adornment because of call to Binding.ofObject
new go.Binding("text", "", function(ad) { return "Connections: " + ad.adornedPart.linksConnected.count; }).ofObject())
) // end Vertical Panel
); // end Adornment
// define the Node template
myDiagram.nodeTemplate =
$(go.Node, "Spot",
{
locationSpot: go.Spot.Center,
selectionAdorned: false,
mouseEnter: function(e, node) { node.layerName = "Foreground"; },
mouseLeave: function(e, node) { node.layerName = ""; },
click: nodeClicked,
toolTip: commonToolTip
},
$(go.Shape, // this always occupies the full circle
{ fill: "lightgray", strokeWidth: 0 },
new go.Binding("geometry", "", makeAnnularWedge),
new go.Binding("fill", "color")),
$(go.TextBlock,
{ width: layerThickness, textAlign: "center" },
new go.Binding("alignment", "", computeTextAlignment),
new go.Binding("angle", "angle", ensureUpright),
new go.Binding("text"))
);
function makeAnnularWedge(data) {
var angle = data.angle;
var sweep = data.sweep;
var radius = data.radius; // the inner radius
if (angle === undefined || sweep === undefined || radius === undefined) return null;
// the Geometry will be centered about (0,0)
var outer = radius + layerThickness; // the outer radius
var inner = radius;
var p = new go.Point(outer, 0).rotate(angle - sweep / 2);
var q = new go.Point(inner, 0).rotate(angle + sweep / 2);
var geo = new go.Geometry()
.add(new go.PathFigure(-outer, -outer)) // always make sure the Geometry includes the top left corner
.add(new go.PathFigure(outer, outer)) // and the bottom right corner of the whole circular area
.add(new go.PathFigure(p.x, p.y) // start at outer corner, go clockwise
.add(new go.PathSegment(go.PathSegment.Arc, angle - sweep / 2, sweep, 0, 0, outer, outer))
.add(new go.PathSegment(go.PathSegment.Line, q.x, q.y)) // to opposite inner corner, then anticlockwise
.add(new go.PathSegment(go.PathSegment.Arc, angle + sweep / 2, -sweep, 0, 0, inner, inner).close()));
return geo;
}
function computeTextAlignment(data) {
var angle = data.angle;
var radius = data.radius;
if (angle === undefined || radius === undefined) return go.Spot.Center;
var p = new go.Point(radius + layerThickness / 2, 0).rotate(angle);
return new go.Spot(0.5, 0.5, p.x, p.y);
}
function ensureUpright(angle) {
if (angle > 90 && angle < 270) return angle + 180;
return angle;
}
// this is the root node, at the center of the circular layers
myDiagram.nodeTemplateMap.add("Root",
$(go.Node, "Auto",
{
locationSpot: go.Spot.Center,
selectionAdorned: false,
toolTip: commonToolTip,
width: layerThickness * 2,
height: layerThickness * 2
},
$(go.Shape, "Circle",
{ fill: "white", strokeWidth: 0.5, spot1: go.Spot.TopLeft, spot2: go.Spot.BottomRight }),
$(go.TextBlock,
{ font: "bold 14pt sans-serif", textAlign: "center" },
new go.Binding("text"))
));
// define the Link template -- don't show anything!
myDiagram.linkTemplate =
$(go.Link);
generateGraph();
}
function generateGraph() {
var names = [
"Joshua", "Daniel", "Robert", "Noah", "Anthony",
"Elizabeth", "Addison", "Alexis", "Ella", "Samantha",
"Joseph", "Scott", "James", "Ryan", "Benjamin",
"Walter", "Gabriel", "Christian", "Nathan", "Simon",
"Isabella", "Emma", "Olivia", "Sophia", "Ava",
"Emily", "Madison", "Tina", "Elena", "Mia",
"Jacob", "Ethan", "Michael", "Alexander", "William",
"Natalie", "Grace", "Lily", "Alyssa", "Ashley",
"Sarah", "Taylor", "Hannah", "Brianna", "Hailey",
"Christopher", "Aiden", "Matthew", "David", "Andrew",
"Kaylee", "Juliana", "Leah", "Anna", "Allison",
"John", "Samuel", "Tyler", "Dylan", "Jonathan"
];
var nodeDataArray = [];
for (var i = 0; i < names.length; i++) {
nodeDataArray.push({ key: i, text: names[i], color: go.Brush.randomColor(128, 240) });
}
var linkDataArray = [];
var num = nodeDataArray.length;
for (var i = 0; i < num * 2; i++) {
var a = Math.floor(Math.random() * num);
var b = Math.floor(Math.random() * num / 4) + 1;
linkDataArray.push({ from: a, to: (a + b) % num, color: go.Brush.randomColor(0, 127) });
}
myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
// layout based on a random person
var someone = nodeDataArray[Math.floor(Math.random() * nodeDataArray.length)];
var somenode = myDiagram.findNodeForData(someone);
nodeClicked(null, somenode);
}
function nodeClicked(e, root) {
var diagram = root.diagram;
if (diagram === null) return;
// all other nodes should be visible and use the default category
diagram.nodes.each(function(n) {
n.visible = true;
if (n !== root) n.category = "";
})
// make this Node the root
root.category = "Root";
// the root node always gets a full circle for itself, just in case the "Root"
// template has any bindings using these properties
diagram.model.setDataProperty(root.data, "angle", 0);
diagram.model.setDataProperty(root.data, "sweep", 360);
diagram.model.setDataProperty(root.data, "radius", 0);
// tell the RadialLayout what the root node should be
// setting this property will automatically invalidate the layout and then perform it again
diagram.layout.root = root;
}
</script>
</head>
<body onload="init()">
<div id="sample">
<div id="myDiagramDiv" style="border: solid 1px black; background: white; width: 100%; height: 600px"></div>
<p>
Click on a Node to center it and show its relationships.
</p>
<p>
The <code>RadialLayout</code> class is an extension defined at <a href="../extensions/RadialLayout.js">RadialLayout.js</a>.
The override of the <code>RadialLayout.rotateNode</code> sets the <code>angle</code>,
<code>sweep</code>, and <code>radius</code> data properties.
Bindings in the node template use those properties to produce the appropriate <a>Shape.geometry</a>
and the <a>GraphObject.alignment</a> and <a>GraphObject.angle</a> for each <a>TextBlock</a>.
</p>
</div>
</body>
</html>