1 | <!DOCTYPE html>
|
2 | <html lang="en">
|
3 | <head>
|
4 | <meta charset="utf-8"/>
|
5 | <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
|
6 |
|
7 | <link rel="stylesheet" href="../assets/css/style.css"/>
|
8 | <title> GoJS Layouts -- Northwoods Software </title>
|
9 | <link rel="stylesheet" href="../assets/css/prism.css" />
|
10 | </head>
|
11 | <script>
|
12 |
|
13 | window.diagrams = [];
|
14 | window.goCode = function(pre, w, h, parentid, animation) {
|
15 | window.diagrams.push([pre, w, h, parentid, animation]);
|
16 | }
|
17 | </script>
|
18 | <body>
|
19 | <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
|
20 | <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
|
21 | <div class="md:pl-4">
|
22 | <a class="text-white hover:text-white no-underline hover:no-underline
|
23 | font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
|
24 | <h1 class="mb-0 p-1 ">GoJS</h1>
|
25 | </a>
|
26 | </div>
|
27 | <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
28 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
29 | <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
|
30 | <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
31 | </svg>
|
32 | </button>
|
33 | <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
|
34 | <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
|
35 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
|
36 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
|
37 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
|
38 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
|
39 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
|
40 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
|
41 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
|
42 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
|
43 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
|
44 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
|
45 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
|
46 | </ul>
|
47 | </div>
|
48 | </div>
|
49 | <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
|
50 | </nav>
|
51 |
|
52 | <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
|
53 |
|
54 | <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
|
55 | <div class="flex-shrink-0 px-8 py-4">
|
56 | <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
57 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
58 | <path id="navOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
|
59 | <path id="navClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
60 | </svg>
|
61 | </button>
|
62 | </div>
|
63 | <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
|
64 | <a href="index.html">Basics</a>
|
65 | <a href="buildingObjects.html">Building Parts</a>
|
66 | <a href="usingModels.html">Using Models</a>
|
67 | <a href="dataBinding.html">Data Binding</a>
|
68 | <a href="react.html">GoJS with React</a>
|
69 | <a href="angular.html">GoJS with Angular</a>
|
70 | <a href="textBlocks.html">TextBlocks</a>
|
71 | <a href="shapes.html">Shapes</a>
|
72 | <a href="pictures.html">Pictures</a>
|
73 | <a href="panels.html">Panels</a>
|
74 | <a href="tablePanels.html">Table Panels</a>
|
75 | <a href="brush.html">Brushes</a>
|
76 | <a href="sizing.html">Sizing Objects</a>
|
77 | <a href="itemArrays.html">Item Arrays</a>
|
78 | <a href="changedEvents.html">Changed Events</a>
|
79 | <a href="transactions.html">Transactions</a>
|
80 | <a href="viewport.html">Coordinates</a>
|
81 | <a href="initialView.html">Initial View</a>
|
82 | <a href="collections.html">Collections</a>
|
83 | <a href="links.html">Links</a>
|
84 | <a href="linkLabels.html">Link Labels</a>
|
85 | <a href="connectionPoints.html">Link Points</a>
|
86 | <a href="ports.html">Ports</a>
|
87 | <a href="nodes.html">Nodes</a>
|
88 | <a href="debugging.html">Debugging</a>
|
89 | <a href="layouts.html">Layouts</a>
|
90 | <a href="trees.html">Trees</a>
|
91 | <a href="subtrees.html">SubTrees</a>
|
92 | <a href="groups.html">Groups</a>
|
93 | <a href="subgraphs.html">SubGraphs</a>
|
94 | <a href="sizedGroups.html">Sized Groups</a>
|
95 | <a href="selection.html">Selection</a>
|
96 | <a href="highlighting.html">Highlighting</a>
|
97 | <a href="animation.html">Animation</a>
|
98 | <a href="toolTips.html">ToolTips</a>
|
99 | <a href="contextmenus.html">Context Menus</a>
|
100 | <a href="events.html">Diagram Events</a>
|
101 | <a href="tools.html">Tools</a>
|
102 | <a href="commands.html">Commands</a>
|
103 | <a href="permissions.html">Permissions</a>
|
104 | <a href="validation.html">Validation</a>
|
105 | <a href="HTMLInteraction.html">HTML Interaction</a>
|
106 | <a href="layers.html">Layers & Z-ordering</a>
|
107 | <a href="palette.html">Palette</a>
|
108 | <a href="overview.html">Overview</a>
|
109 | <a href="resizing.html">Resizing Diagrams</a>
|
110 | <a href="replacingDeleting.html">Replacing and Deleting</a>
|
111 | <a href="buttons.html">Buttons</a>
|
112 | <a href="templateMaps.html">Template Maps</a>
|
113 | <a href="legends.html">Legends and Titles</a>
|
114 | <a href="extensions.html">Extensions</a>
|
115 | <a href="geometry.html">Geometry Strings</a>
|
116 | <a href="grids.html">Grid Patterns</a>
|
117 | <a href="graduatedPanels.html">Graduated Panels</a>
|
118 | <a href="makingImages.html">Diagram Images</a>
|
119 | <a href="makingSVG.html">Diagram SVG</a>
|
120 | <a href="printing.html">Printing</a>
|
121 | <a href="serverSideImages.html">Server-side Images</a>
|
122 | <a href="nodeScript.html">GoJS in Node.js</a>
|
123 | <a href="testing.html">Testing</a>
|
124 | <a href="storage.html">Storage</a>
|
125 | <a href="performance.html">Performance</a>
|
126 | <a href="source.html">Building from Source</a>
|
127 | <a href="platforms.html">Platforms</a>
|
128 | <a href="deployment.html">Deployment</a>
|
129 | </nav>
|
130 | </div>
|
131 | <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">
|
132 |
|
133 |
|
134 |
|
135 |
|
136 | <h1>Diagram Layouts</h1>
|
137 | <p>
|
138 | In general terms, a "layout" is a way of sizing and positioning a collection of objects.
|
139 | HTML has its own layouts for its HTML elements.
|
140 | In <b>GoJS</b> you have already seen many examples of Panel layout, such as Auto or Table,
|
141 | which sizes and positions <a>GraphObject</a>s within a <a>Panel</a>.
|
142 | <b>GoJS</b> also provides Diagram layouts, which position <a>Node</a>s and route <a>Link</a>s
|
143 | within a <a>Diagram</a> or a <a>Group</a>.
|
144 | </p>
|
145 |
|
146 | <p>
|
147 | Naturally the principal purpose of each diagram <a>Layout</a> is to position nodes, typically by calling <a>Part.move</a>.
|
148 | But layouts also may also result in custom routing of the links, by setting properties on each <a>Link</a>.
|
149 | For example <a>TreeLayout</a> also ensures that links are routed in the expected direction by setting
|
150 | <a>Link.fromSpot</a> and <a>Link.toSpot</a> depending on the <a>TreeLayout.angle</a>.
|
151 | (However, that behavior can be disabled by setting <a>TreeLayout.setsPortSpot</a> and <a>TreeLayout.setsChildPortSpot</a>.
|
152 | The same is true for some other layouts.)
|
153 | </p>
|
154 |
|
155 | <p>
|
156 | Diagram layouts can be accomplished in several manners.
|
157 | Manual layouts occur because the user moves nodes, thereby establishing new positions for those nodes.
|
158 | Such layouts might be saved in some persistent data format and later loaded using data binding or assignments in code.
|
159 | Programmatic layouts happen when some code executes to set the <a>Part</a> position or location.
|
160 | Automatic layouts are programmatic layouts that are implemented by the <a>Layout</a> class or its subclasses.
|
161 | </p>
|
162 |
|
163 | <h2 id="DefaultLayout">Default Layout</h2>
|
164 | <p>
|
165 | The value of <a>Diagram.layout</a> defaults to an instance of <a>Layout</a>.
|
166 | This kind of layout is unlike all of the other layout subclasses, in that it only sets the position of nodes
|
167 | that do not already have a position -- i.e. where the X or Y of the <a>GraphObject.actualBounds</a> is NaN.
|
168 | It leaves unmodified all nodes that do have a defined position, and it ignores all links.
|
169 | </p>
|
170 |
|
171 | <p>
|
172 | Many of the examples you have seen so far do not set <a>Diagram.layout</a> and thus use the default layout.
|
173 | Some of the examples data bind the <a>Part.location</a> or <a>GraphObject.position</a> to a data property.
|
174 | Those examples are basically using manual layout, but with the node positions coming from the node data rather than from
|
175 | arrangement by the user.
|
176 | </p>
|
177 |
|
178 | <p>
|
179 | However many of the examples just allow the standard behavior of the <a>Layout</a> class to assign positions to the nodes
|
180 | in the order in which they are seen by the layout.
|
181 | Those examples are exhibiting automatic layout behavior.
|
182 | </p>
|
183 |
|
184 | <h2 id="AutomaticLayouts">Automatic Layouts</h2>
|
185 | <p>
|
186 | <b>GoJS</b> offers several kinds of automatic layouts, including:
|
187 | </p>
|
188 | <ul>
|
189 | <li><a>GridLayout</a></li>
|
190 | <li><a>TreeLayout</a></li>
|
191 | <li><a>ForceDirectedLayout</a></li>
|
192 | <li><a>LayeredDigraphLayout</a></li>
|
193 | <li><a>CircularLayout</a></li>
|
194 | </ul>
|
195 |
|
196 | <p>
|
197 | There are samples for each of these layouts, demonstrating the effects of setting various detailed layout properties:
|
198 | </p>
|
199 | <ul>
|
200 | <li><a href="../samples/gLayout.html" target="samples">GridLayout Sample</a></li>
|
201 | <li><a href="../samples/tLayout.html" target="samples">TreeLayout Sample</a></li>
|
202 | <li><a href="../samples/fdLayout.html" target="samples">ForceDirectedLayout Sample</a></li>
|
203 | <li><a href="../samples/ldLayout.html" target="samples">LayeredDigraphLayout Sample</a></li>
|
204 | <li><a href="../samples/cLayout.html" target="samples">CircularLayout Sample</a></li>
|
205 | </ul>
|
206 |
|
207 | <p>
|
208 | In the introduction pages and samples you will see many examples that make use of automatic layout by setting the <a>Diagram.layout</a> property. <a href="https://github.com/NorthwoodsSoftware/GoJS/search?utf8=%E2%9C%93&q=%22layout%3A+%26%28go%22&type=Code">Search the sources of the samples for many more examples.</a>
|
209 | </p>
|
210 |
|
211 | <h3 id="LayoutUsage">Layout Usage</h3>
|
212 |
|
213 | <p>
|
214 | You can set <a>Diagram.layout</a> in a JavaScript statement:
|
215 | </p>
|
216 | <pre class="lang-js"><code>diagram.layout = new go.ForceDirectedLayout();</code></pre>
|
217 | <p>
|
218 | Or you can initialize that property using <a>GraphObject,make</a>:
|
219 | </p>
|
220 | <pre class="lang-js"><code>
|
221 | var diagram = $(go.Diagram, "myDiagramDiv",
|
222 | {
|
223 | layout: $(go.TreeLayout,
|
224 | { angle: 90, nodeSpacing: 10, layerSpacing: 30 })
|
225 | });
|
226 | </code></pre>
|
227 | <p>
|
228 | We recommend using <b>GraphObject.make</b> whenever you can because of the error checking that it does for property names.
|
229 | </p>
|
230 |
|
231 | <h3 id="GridLayout">Grid Layout</h3>
|
232 |
|
233 | <p>A simple layout for placing Nodes in a grid-like arrangement.</p>
|
234 |
|
235 | <pre class="lang-js" id="gridlayout" style="display: none;"><code>
|
236 | diagram.layout = $(go.GridLayout);
|
237 | diagram.contentAlignment = go.Spot.Center;
|
238 |
|
239 | // define a simple Node template
|
240 | diagram.nodeTemplate =
|
241 | $(go.Node, "Spot", // the Shape will go around the TextBlock
|
242 | $(go.Shape, "Ellipse",
|
243 | { fill: 'palegreen', stroke: '#333', strokeWidth: 3, width: 40, height: 40 }
|
244 | ),
|
245 | $(go.TextBlock,
|
246 | { margin: 3, font: 'bold 14px sans-serif', stroke: '#333' }, // some room around the text
|
247 | // TextBlock.text is bound to Node.data.key
|
248 | new go.Binding("text", "key"))
|
249 | );
|
250 |
|
251 | diagram.linkTemplate =
|
252 | $(go.Link,
|
253 | // Default routing is go.Link.Normal
|
254 | // Default corner is 0
|
255 | { corner: 5 },
|
256 | $(go.Shape, { strokeWidth: 3, stroke: "#333" })
|
257 | );
|
258 |
|
259 | // create the model data that will be represented by Nodes and Links
|
260 | diagram.model = new go.GraphLinksModel(
|
261 | [
|
262 | { key: "1" },
|
263 | { key: "2" },
|
264 | { key: "3" },
|
265 | { key: "4" },
|
266 | { key: "5" },
|
267 | { key: "6" },
|
268 | { key: "7" },
|
269 | { key: "8" },
|
270 | { key: "9" },
|
271 | { key: "10" },
|
272 | { key: "11" },
|
273 | ],
|
274 | [
|
275 | ]);
|
276 | </code></pre>
|
277 | <script>goCode("gridlayout", 400, 120)</script>
|
278 |
|
279 | <p>
|
280 | See the <a href="../samples/gLayout.html" target="samples">GridLayout Sample</a> for a demonstration of layout options.
|
281 | The <a href="../samples/swimlanes.html" target="samples">Swim Lanes</a> sample demonstrates a customization of <a>GridLayout</a>.
|
282 | See more samples that make use of <a>GridLayout</a> in the <a href="../samples/index.html#gridlayout">samples index</a>.
|
283 | </p>
|
284 |
|
285 | <h id="TreeLayout">Tree Layout</h>
|
286 |
|
287 | <p>This layout positions nodes of a tree-structured graph in layers (rows or columns).</p>
|
288 |
|
289 | <pre class="lang-js" id="treelayout" style="display: none;"><code>
|
290 | diagram.layout = $(go.TreeLayout);
|
291 | diagram.contentAlignment = go.Spot.Center;
|
292 |
|
293 | // define a simple Node template
|
294 | diagram.nodeTemplate =
|
295 | $(go.Node, "Spot", // the Shape will go around the TextBlock
|
296 | $(go.Shape, "Ellipse",
|
297 | { fill: 'palegreen', stroke: '#333', strokeWidth: 3, width: 40, height: 40 }
|
298 | ),
|
299 | $(go.TextBlock,
|
300 | { margin: 3, font: 'bold 14px sans-serif', stroke: '#333' }, // some room around the text
|
301 | // TextBlock.text is bound to Node.data.key
|
302 | new go.Binding("text", "key"))
|
303 | );
|
304 |
|
305 | diagram.linkTemplate =
|
306 | $(go.Link,
|
307 | // Default routing is go.Link.Normal
|
308 | // Default corner is 0
|
309 | { corner: 5 },
|
310 | $(go.Shape, { strokeWidth: 3, stroke: "#333" })
|
311 | );
|
312 |
|
313 | // create the model data that will be represented by Nodes and Links
|
314 | diagram.model = new go.GraphLinksModel(
|
315 | [
|
316 | { key: "1" },
|
317 | { key: "2" },
|
318 | { key: "3" },
|
319 | { key: "4" },
|
320 | { key: "5" },
|
321 | { key: "6" }
|
322 | ],
|
323 | [
|
324 | { from: "1", to: "2" },
|
325 | { from: "1", to: "3" },
|
326 | { from: "3", to: "4" },
|
327 | { from: "3", to: "5" },
|
328 | { from: "3", to: "6" }
|
329 | ]);
|
330 | </code></pre>
|
331 | <script>goCode("treelayout", 400, 200)</script>
|
332 |
|
333 | <p>
|
334 | See the <a href="../samples/tLayout.html" target="samples">TreeLayout sample</a> for a demonstration of layout options.
|
335 | The <a href="../samples/orgChartEditor.html" target="samples">Org Chart Editor</a>,
|
336 | <a href="../samples/parseTree.html" target="samples">Parse Tree</a>,
|
337 | <a href="../samples/swimBands.html" target="samples">Layer Bands</a>, and
|
338 | <a href="../samples/virtualizedTreeLayout.html" target="samples">Virtualized Tree</a>
|
339 | samples demonstrate customization of <a>TreeLayout</a>.
|
340 | See more samples that make use of <a>TreeLayout</a> in the <a href="../samples/index.html#treelayout">samples index</a>.
|
341 | </p>
|
342 |
|
343 | <h3 id="ForceDirectedLayout">Force-Directed Layout</h3>
|
344 |
|
345 | <p>Force-directed layout treats the graph as if it were a system of physical bodies with forces acting on them and between them.</p>
|
346 |
|
347 | <pre class="lang-js" id="fdlayout" style="display: none;"><code>
|
348 | diagram.layout = $(go.ForceDirectedLayout);
|
349 | diagram.initialAutoScale = go.Diagram.Uniform;
|
350 | diagram.contentAlignment = go.Spot.Center;
|
351 |
|
352 | // define a simple Node template
|
353 | diagram.nodeTemplate =
|
354 | $(go.Node, "Spot", // the Shape will go around the TextBlock
|
355 | $(go.Shape, "Ellipse",
|
356 | { fill: 'palegreen', stroke: '#333', strokeWidth: 3, width: 40, height: 40 }
|
357 | ),
|
358 | $(go.TextBlock,
|
359 | { margin: 3, font: 'bold 14px sans-serif', stroke: '#333' }, // some room around the text
|
360 | // TextBlock.text is bound to Node.data.key
|
361 | new go.Binding("text", "key"))
|
362 | );
|
363 |
|
364 | diagram.linkTemplate =
|
365 | $(go.Link,
|
366 | // Default routing is go.Link.Normal
|
367 | // Default corner is 0
|
368 | { corner: 5 },
|
369 | $(go.Shape, { strokeWidth: 3, stroke: "#333" })
|
370 | );
|
371 |
|
372 | // create the model data that will be represented by Nodes and Links
|
373 | diagram.model = new go.GraphLinksModel(
|
374 | [
|
375 | { key: "1" },
|
376 | { key: "2" },
|
377 | { key: "3" },
|
378 | { key: "4" },
|
379 | { key: "5" },
|
380 | { key: "6" },
|
381 | { key: "7" },
|
382 | { key: "8" },
|
383 | { key: "9" },
|
384 | { key: "10" },
|
385 | { key: "11" },
|
386 | ],
|
387 | [
|
388 | { from: "6", to: "2" },
|
389 | { from: "3", to: "4" },
|
390 | { from: "3", to: "5" },
|
391 | { from: "3", to: "6" },
|
392 | { from: "6", to: "1" },
|
393 | { from: "6", to: "7" },
|
394 | { from: "4", to: "8" },
|
395 | { from: "4", to: "9" },
|
396 | { from: "4", to: "10" },
|
397 | { from: "4", to: "11" },
|
398 | ]);
|
399 | </code></pre>
|
400 | <script>goCode("fdlayout", 400, 200)</script>
|
401 |
|
402 | <p>
|
403 | See the <a href="../samples/fdLayout.html" target="samples">ForceDirectedLayout sample</a> for a demonstration of layout options.
|
404 | That sample also demonstrates a simple customization of <a>ForceDirectedLayout</a>.
|
405 | The <a href="../samples/virtualizedForceLayout.html" target="samples">Virtualized Force Directed</a> sample
|
406 | demonstrates a more complicated customization of <a>ForceDirectedLayout</a>.
|
407 | See more samples that make use of <a>ForceDirectedLayout</a> in the <a href="../samples/index.html#forcedirectedlayout">samples index</a>.
|
408 | </p>
|
409 |
|
410 | <h3 id="LayeredDigraphLayout">Layered Digraph Layout</h3>
|
411 |
|
412 | <p>This arranges nodes of directed graphs into layers (rows or columns).</p>
|
413 |
|
414 | <pre class="lang-js" id="ldllayout" style="display: none;"><code>
|
415 | diagram.layout = $(go.LayeredDigraphLayout);
|
416 | diagram.contentAlignment = go.Spot.Center;
|
417 |
|
418 | // define a simple Node template
|
419 | diagram.nodeTemplate =
|
420 | $(go.Node, "Spot", // the Shape will go around the TextBlock
|
421 | $(go.Shape, "Ellipse",
|
422 | { fill: 'palegreen', stroke: '#333', strokeWidth: 3, width: 40, height: 40 }
|
423 | ),
|
424 | $(go.TextBlock,
|
425 | { margin: 3, font: 'bold 14px sans-serif', stroke: '#333' }, // some room around the text
|
426 | // TextBlock.text is bound to Node.data.key
|
427 | new go.Binding("text", "key"))
|
428 | );
|
429 |
|
430 | diagram.linkTemplate =
|
431 | $(go.Link,
|
432 | // Default routing is go.Link.Normal
|
433 | // Default corner is 0
|
434 | { corner: 5 },
|
435 | $(go.Shape, { strokeWidth: 3, stroke: "#333" })
|
436 | );
|
437 |
|
438 | // create the model data that will be represented by Nodes and Links
|
439 | diagram.model = new go.GraphLinksModel(
|
440 | [
|
441 | { key: "1" },
|
442 | { key: "2" },
|
443 | { key: "3" },
|
444 | { key: "4" },
|
445 | { key: "5" },
|
446 | { key: "6" },
|
447 | { key: "7" },
|
448 | ],
|
449 | [
|
450 | { from: "1", to: "2" },
|
451 | { from: "1", to: "3" },
|
452 | { from: "3", to: "4" },
|
453 | { from: "3", to: "5" },
|
454 | { from: "3", to: "6" },
|
455 | { from: "2", to: "5" },
|
456 | { from: "1", to: "5" },
|
457 | { from: "1", to: "7" },
|
458 | { from: "6", to: "7" },
|
459 | ]);
|
460 | </code></pre>
|
461 | <script>goCode("ldllayout", 400, 300)</script>
|
462 |
|
463 | <p>
|
464 | See the <a href="../samples/ldLayout.html" target="samples">LayeredDigraphLayout sample</a> for a demonstration of layout options.
|
465 | The <a href="../samples/genogram.html" target="samples">Genogram</a> sample demonstrates a complex customization of <a>LayeredDigraphLayout</a>.
|
466 | See more samples that make use of <a>LayeredDigraphLayout</a> in the <a href="../samples/index.html#layereddigraphlayout">samples index</a>.
|
467 | </p>
|
468 |
|
469 | <h3 id="CircularLayout">Circular Layout</h3>
|
470 |
|
471 | <p>This layout positions nodes in a circular or elliptical arrangement.</p>
|
472 |
|
473 | <pre class="lang-js" id="circularLayout" style="display: none;"><code>
|
474 | diagram.layout = $(go.CircularLayout);
|
475 | diagram.contentAlignment = go.Spot.Center;
|
476 |
|
477 | // define a simple Node template
|
478 | diagram.nodeTemplate =
|
479 | $(go.Node, "Spot", // the Shape will go around the TextBlock
|
480 | $(go.Shape, "Ellipse",
|
481 | { fill: 'palegreen', stroke: '#333', strokeWidth: 3, width: 40, height: 40 }
|
482 | ),
|
483 | $(go.TextBlock,
|
484 | { margin: 3, font: 'bold 14px sans-serif', stroke: '#333' }, // some room around the text
|
485 | // TextBlock.text is bound to Node.data.key
|
486 | new go.Binding("text", "key"))
|
487 | );
|
488 |
|
489 | diagram.linkTemplate =
|
490 | $(go.Link,
|
491 | // Default routing is go.Link.Normal
|
492 | // Default corner is 0
|
493 | { corner: 5 },
|
494 | $(go.Shape, { strokeWidth: 3, stroke: "#333" })
|
495 | );
|
496 |
|
497 | // create the model data that will be represented by Nodes and Links
|
498 | diagram.model = new go.GraphLinksModel(
|
499 | [
|
500 | { key: "1" },
|
501 | { key: "2" },
|
502 | { key: "3" },
|
503 | { key: "4" },
|
504 | { key: "5" },
|
505 | { key: "6" },
|
506 | { key: "7" },
|
507 | ],
|
508 | [
|
509 | { from: "1", to: "2" },
|
510 | { from: "1", to: "3" },
|
511 | { from: "3", to: "4" },
|
512 | { from: "3", to: "5" },
|
513 | { from: "3", to: "6" },
|
514 | { from: "2", to: "5" },
|
515 | { from: "1", to: "5" },
|
516 | { from: "1", to: "7" },
|
517 | { from: "6", to: "7" },
|
518 | ]);
|
519 | </code></pre>
|
520 | <script>goCode("circularLayout", 400, 200)</script>
|
521 |
|
522 | <p>
|
523 | See the <a href="../samples/cLayout.html" target="samples">CircularLayout sample</a> for a demonstration of layout options.
|
524 | The <a href="../samples/friendWheel.html" target="samples">Friend Wheel</a> sample demonstrates a simple customization of <a>CircularLayout</a>.
|
525 | See more samples that make use of <a>CircularLayout</a> in the <a href="../samples/index.html#circularlayout">samples index</a>.
|
526 | </p>
|
527 |
|
528 |
|
529 | <h3 id="CustomLayouts">Custom Layouts</h3>
|
530 |
|
531 | <p>
|
532 | GoJS allows for the creation of custom layouts.
|
533 | The intro page on <a href="extensions.html">GoJS extensions</a> gives a simple example of a custom layout.
|
534 | See more samples that make use of custom layouts in the <a href="../samples/index.html#customlayout">samples index</a>.
|
535 | </p>
|
536 | <p>
|
537 | There are also many layouts that are extensions -- not predefined in the <code>go.js</code> or <code>go-debug.js</code> library,
|
538 | but available as source code in one of the three extension directories, with some documentation, and with corresponding samples.
|
539 | </p>
|
540 | <ul>
|
541 | <li><a>DoubleTreeLayout</a>: sample at <a href="../samples/doubleTree.html" target="samples">DoubleTreeLayout Sample</a>, defined in <a href="../extensions/DoubleTreeLayout.js">DoubleTreeLayout.js</a></li>
|
542 | <li><a>FishboneLayout</a>: sample at <a href="../extensions/Fishbone.html" target="samples">FishboneLayout Sample</a>, defined in <a href="../extensions/FishboneLayout.js">FishboneLayout.js</a></li>
|
543 | <li><a>PackedLayout</a>: sample at <a href="../extensions/PackedLayout.html" target="samples">PackedLayout Sample</a>, defined in <a href="../extensionsTS/PackedLayout.js">PackedLayout.js</a></li>
|
544 | <li><a>ParallelLayout</a>: sample at <a href="../extensions/Parallel.html" target="samples">ParallelLayout Sample</a>, defined in <a href="../extensions/ParallelLayout.js">ParallelLayout.js</a></li>
|
545 | <li><a>SepentineLayout</a>: sample at <a href="../extensions/Serpentine.html" target="samples">SerpentineLayout Sample</a>, defined in <a href="../extensions/SerpentineLayout.js">SerpentineLayout.js</a></li>
|
546 | <li><a>SpiralLayout</a>: sample at <a href="../extensions/Spiral.html" target="samples">SpiralLayout Sample</a>, defined in <a href="../extensions/SpiralLayout.js">SpiralLayout.js</a></li>
|
547 | <li><a>SwimLaneLayout</a>: sample at <a href="../extensions/SwimLaneLayout.html" target="samples">SwimLaneLayout Sample</a>, defined in <a href="../extensionsTS/SwimLaneLayout.js">SwimLaneLayout.js</a></li>
|
548 | <li><a>TableLayout</a>: sample at <a href="../extensions/Table.html" target="samples">TableLayout Sample</a>, defined in <a href="../extensions/TableLayout.js">TableLayout.js</a></li>
|
549 | <li><a>TreeMapLayout</a>: sample at <a href="../extensions/TreeMap.html" target="samples">TreeMapLayout Sample</a>, defined in <a href="../extensions/TreeMapLayout.js">TreeMapLayout.js</a></li>
|
550 | </ul>
|
551 |
|
552 |
|
553 | <h2 id="LayoutInvalidation">Layout Invalidation</h2>
|
554 | <p>
|
555 | A layout is considered "valid" when it has performed its positioning of its nodes and perhaps routed its links.
|
556 | However some kinds of changes cause a layout to become "invalid", thereby causing it to be performed again in the near future.
|
557 | Because layouts can be computationally expensive, automatic layouts are not performed as soon as a layout is invalidated.
|
558 | Instead they are typically performed at the end of a transaction.
|
559 | </p>
|
560 | <p>
|
561 | The most common reasons for a layout to be invalidated are because a node or a link has been added or removed from the collection
|
562 | of nodes and links that a layout is responsible for, or because a node or a link has changed visibility, or because a node has changed size.
|
563 | If you do not want an automatic layout to happen when such a change occurs, it may be easiest to set <a>Layout.isOngoing</a> to false.
|
564 | </p>
|
565 | <p>
|
566 | Another common situation is where you have set <a>Diagram.layout</a> to some kind of layout but you want to load a diagram (model)
|
567 | that contains manually positioned or adjusted node locations. The <a>Binding</a> of <a>Part.location</a> to the model data is effective,
|
568 | but the locations are lost when a layout is performed immediately after loading. This situation can be avoided by setting
|
569 | <a>Layout.isInitial</a> to false. After the initial layout the layout might still be invalidated by adding or removing or changing
|
570 | the visibility of a node or a link or by a change in node size, unless you have also set <a>Layout.isOngoing</a> to false.
|
571 | When both <a>Layout.isInitial</a> and <a>Layout.isOngoing</a> are false, you can still explicitly cause a layout to happen by either
|
572 | calling <a>Layout.invalidateLayout</a> or by calling <a>Diagram.layoutDiagram</a> with a <code>true</code> argument.
|
573 | </p>
|
574 | <p>
|
575 | For example, in editors it is commonplace to have TwoWay Bindings on <a>Node.location</a> to save manually adjusted node locations.
|
576 | This means that saved models will have saved locations for all of the nodes.
|
577 | But if you create a new model without all of the node data objects having real locations,
|
578 | you will want a layout to be performed initially when the model is loaded.
|
579 | You can accomplish this by setting <a>Layout.isInitial</a> to false
|
580 | (and optionally <a>Layout.isOngoing</a> to false, if that is what you want when users add or remove nodes or links)
|
581 | and then implementing an "InitialLayoutCompleted" <a>DiagramEvent</a> listener that decides whether a layout is needed.
|
582 | The decision could be to look at a flag that you add to the <a>Model.modelData</a>.
|
583 | Or you could look at all of the nodes to make sure their locations have real values:
|
584 | </p>
|
585 | <pre class="lang-js"><code>
|
586 | $(go.Diagram, . . .,
|
587 | {
|
588 | . . .,
|
589 | layout: $(go.TreeLayout, { isInitial: false, isOngoing: false }, . . .),
|
590 | "InitialLayoutCompleted": function(e) {
|
591 | // if not all Nodes have real locations, force a layout to happen
|
592 | if (!e.diagram.nodes.all(function(n) { return n.location.isReal(); })) {
|
593 | e.diagram.layoutDiagram(true);
|
594 | }
|
595 | }
|
596 | })
|
597 | </code></pre>
|
598 | <p>
|
599 | But if you do not want a change to a particular Node or Link to cause an automatic layout, yet you do want that invalidation for other Nodes or Links,
|
600 | you can set the <a>Part.layoutConditions</a> property to the combination of <a>Part</a> "Layout..." flags that suits your needs.
|
601 | It is most common to not want a layout for the <a>Part,LayoutNodeSized</a> condition:
|
602 | </p>
|
603 | <pre class="lang-js"><code>
|
604 | $(go.Node, . . .,
|
605 | { layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized },
|
606 | . . .
|
607 | )
|
608 | </code></pre>
|
609 | <p>
|
610 | Parts that remain not visible or that are in layers that are <a>Layer.isTemporary</a> also never invalidate any Layout.
|
611 | </p>
|
612 | <p>
|
613 | Finally, you can set <a>Part.isLayoutPositioned</a> to false in order for the Layout to completely ignore that Part.
|
614 | But you will have to make sure that that Part does have a real <a>Part.location</a>, since no layout will set it for you.
|
615 | Without a real location the part will not be visible anywhere in the diagram.
|
616 | Furthermore if a node has isLayoutPositioned set to false, Layouts will not only ignore that node but also all links connecting with that node.
|
617 | Because the node will not be moved by the layout, it might overlap with the laid-out nodes and links.
|
618 | You can also set or bind <a>Part.isLayoutPositioned</a> to false on Links in order to have the layout ignore those links.
|
619 | This is demonstrated in <a href="../samples/orgChartExtras.html" target="samples">Org Chart Extras</a>.
|
620 | </p>
|
621 |
|
622 | </div>
|
623 | </div>
|
624 |
|
625 | <div class="bg-nwoods-primary">
|
626 | <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
|
627 | <p id="version" class="leading-none mb-2 my-4">GoJS</p>
|
628 | </section>
|
629 | </div><footer class="bg-nwoods-primary text-white">
|
630 | <div class="container max-w-screen-lg mx-auto px-8">
|
631 | <div class="w-full py-6">
|
632 |
|
633 | <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
|
634 | <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
|
635 | <li class="list-none row-span-2">
|
636 | <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
|
637 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
638 | <li>
|
639 | <a href="../samples/index.html">Samples</a>
|
640 | </li>
|
641 | <li>
|
642 | <a href="../learn/index.html">Learn</a>
|
643 | </li>
|
644 | <li>
|
645 | <a href="../intro/index.html">Intro</a>
|
646 | </li>
|
647 | <li>
|
648 | <a href="../api/index.html">API</a>
|
649 | </li>
|
650 | <li>
|
651 | <a href="../changelog.html">Changelog</a>
|
652 | </li>
|
653 | <li>
|
654 | <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
|
655 | </li>
|
656 | </ul>
|
657 | </li>
|
658 | <li class="list-none row-span-2">
|
659 | <h2 class="text-base font-semibold tracking-wide">Support</h2>
|
660 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
661 | <li>
|
662 | <a href="https://www.nwoods.com/contact.html"
|
663 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
|
664 | </li>
|
665 | <li>
|
666 | <a href="https://forum.nwoods.com/c/gojs">Forum</a>
|
667 | </li>
|
668 | <li>
|
669 | <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
|
670 | </li>
|
671 | <li>
|
672 | <a href="https://www.nwoods.com/sales/index.html"
|
673 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
|
674 | </li>
|
675 | <li>
|
676 | <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
|
677 | </li>
|
678 | </ul>
|
679 | </li>
|
680 | <li class="list-none row-span-2">
|
681 | <h2 class="text-base font-semibold tracking-wide">Company</h2>
|
682 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
683 | <li>
|
684 | <a href="https://www.nwoods.com">Northwoods</a>
|
685 | </li>
|
686 | <li>
|
687 | <a href="https://www.nwoods.com/about.html">About Us</a>
|
688 | </li>
|
689 | <li>
|
690 | <a href="https://www.nwoods.com/contact.html">Contact Us</a>
|
691 | </li>
|
692 | <li>
|
693 | <a href="https://twitter.com/northwoodsgo">Twitter</a>
|
694 | </li>
|
695 |
|
696 | </ul>
|
697 | </li>
|
698 | </ul>
|
699 |
|
700 |
|
701 | <p class="text-sm text-gray-100 md:mb-6">
|
702 | Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
|
703 | </p>
|
704 | </div>
|
705 | </div>
|
706 | </footer> </body>
|
707 |
|
708 | <script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
|
709 | <script>
|
710 | window.dataLayer = window.dataLayer || [];
|
711 | function gtag(){dataLayer.push(arguments);}
|
712 | gtag('js', new Date()); gtag('config', 'UA-1506307-5');
|
713 | var getOutboundLink = function(url, label) {
|
714 | gtag('event', 'click', {
|
715 | 'event_category': 'outbound',
|
716 | 'event_label': label,
|
717 | 'transport_type': 'beacon'
|
718 | });
|
719 | }
|
720 |
|
721 |
|
722 | var topButton = document.getElementById("topnavButton");
|
723 | var topnavList = document.getElementById("topnavList");
|
724 | topButton.addEventListener("click", function() {
|
725 | this.classList.toggle("active");
|
726 | topnavList.classList.toggle("hidden");
|
727 | document.getElementById("topnavOpen").classList.toggle("hidden");
|
728 | document.getElementById("topnavClosed").classList.toggle("hidden");
|
729 | });
|
730 | </script>
|
731 | <script src="../assets/js/prism.js"></script>
|
732 | <script src="../release/go.js"></script>
|
733 | <script src="../assets/js/goDoc.js"></script>
|
734 | <script>
|
735 | document.addEventListener("DOMContentLoaded", function() {
|
736 | if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
|
737 | if (window.goDoc) window.goDoc();
|
738 | var d = window.diagrams;
|
739 | for (var i = 0; i < d.length; i++) {
|
740 | var dargs = d[i];
|
741 | goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
|
742 | }
|
743 | if (window.extra) window.extra();
|
744 | });
|
745 | </script>
|
746 | </html>
|