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 | <meta name="description" content="Tutorial for getting started with GoJS."/>
|
7 | <link rel="stylesheet" href="../assets/css/style.css"/>
|
8 | <title> Get Started with GoJS </title>
|
9 | <link rel="stylesheet" href="../assets/css/prism.css" />
|
10 |
|
11 | <script src="../release/go.js"></script>
|
12 | </head>
|
13 | <body>
|
14 | <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
|
15 | <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">
|
16 | <div class="md:pl-4">
|
17 | <a class="text-white hover:text-white no-underline hover:no-underline
|
18 | font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
|
19 | <h1 class="mb-0 p-1 ">GoJS</h1>
|
20 | </a>
|
21 | </div>
|
22 | <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
23 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
24 | <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>
|
25 | <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>
|
26 | </svg>
|
27 | </button>
|
28 | <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
|
29 | <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
|
30 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
|
31 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
|
32 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
|
33 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
|
34 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
|
35 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
|
36 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
|
37 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
|
38 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
|
39 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
|
40 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
|
41 | </ul>
|
42 | </div>
|
43 | </div>
|
44 | <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
|
45 | </nav>
|
46 |
|
47 | <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
|
48 |
|
49 | <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
|
50 | <div class="flex-shrink-0 px-8 py-4">
|
51 | <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
52 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
53 | <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>
|
54 | <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>
|
55 | </svg>
|
56 | </button>
|
57 | </div>
|
58 | <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">
|
59 | <a href="../learn/index.html">Get Started</a>
|
60 | <a href="../learn/graphObject.html">Manipulating GraphObjects</a>
|
61 | <a href="../learn/interactivity.html">Interacting with Diagrams</a>
|
62 | </nav>
|
63 | </div>
|
64 | <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">
|
65 |
|
66 | <h1>Get Started with GoJS</h1>
|
67 |
|
68 | <h2 id="GoJSTutorials">GoJS Tutorials</h2>
|
69 | <p>
|
70 | For video tutorials, see our
|
71 | <a href="https://www.nwoods.com/videos.html">YouTube videos</a>. For textual
|
72 | tutorials, read on.
|
73 | </p>
|
74 |
|
75 | <p>
|
76 | <b>GoJS</b> is a JavaScript library for implementing interactive diagrams.
|
77 | This page will show you the essentials of using <b>GoJS</b>.
|
78 | We assume you are a programmer who is familiar with HTML, CSS, and JavaScript.
|
79 | </p>
|
80 |
|
81 | <p>
|
82 | First, let's load the GoJS library. If you have the library downloaded to your machine:
|
83 | </p>
|
84 |
|
85 | <pre class="lang-html"><code>
|
86 | <!-- use go-debug.js when developing and go.js when deploying -->
|
87 | <script src="go-debug.js"></script>
|
88 | </code></pre>
|
89 |
|
90 | <p>
|
91 | You can download <b>GoJS</b> and all the documentation and samples from
|
92 | <a target="_blank" href="../download.html">here</a>.
|
93 | </p>
|
94 |
|
95 | <p>
|
96 | Alternatively you can link straight to a <b>GoJS</b> library provided by a
|
97 | <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/CDN">CDN</a>
|
98 | such as:
|
99 | </p>
|
100 |
|
101 | <pre class="lang-html"><code>
|
102 | <script src="https://unpkg.com/gojs/release/go-debug.js"></script></code></pre>
|
103 | <p>
|
104 | Each <b>GoJS</b> diagram is contained in an HTML
|
105 | <code><div></code> element in your HTML page that you give an explicit
|
106 | size:
|
107 | </p>
|
108 |
|
109 | <pre class="lang-html"><code>
|
110 | <!-- The DIV for a Diagram needs an explicit size or else we will not see anything.
|
111 | In this case we also add a background color so we can see that area. -->
|
112 | <div id="myDiagramDiv"
|
113 | style="width:400px; height:150px; background-color: #DAE4E4;"></div>
|
114 | </code></pre>
|
115 |
|
116 | <p>
|
117 | In JavaScript code you pass the <code><div></code>'s
|
118 | <code>id</code> when making a Diagram:
|
119 | </p>
|
120 |
|
121 | <pre class="lang-js"><code>
|
122 | var $ = go.GraphObject.make;
|
123 |
|
124 | var myDiagram =
|
125 | $(go.Diagram, "myDiagramDiv");
|
126 | </code></pre>
|
127 |
|
128 | <p>Together, this creates an empty diagram:</p>
|
129 |
|
130 |
|
131 | <div id="myDiagramDiv" class="diagramStyling" style="width: 400px; height: 150px"></div>
|
132 | <script>
|
133 | var $ = go.GraphObject.make;
|
134 |
|
135 | var myDiagram =
|
136 | $(go.Diagram, "myDiagramDiv");
|
137 | </script>
|
138 |
|
139 | <p>
|
140 | Notice that <code>go</code> is the "namespace" in which all <b>GoJS</b> types
|
141 | reside. All code uses of <b>GoJS</b> classes such as Diagram or Node or Panel
|
142 | or Shape or TextBlock will be prefixed with "<code>go.</code>".
|
143 | </p>
|
144 | <p>
|
145 | This article will show you by example how to use
|
146 | <code>go.GraphObject.make</code> to build <b>GoJS</b> objects. For more
|
147 | detail, read
|
148 | <a href="../intro/buildingObjects.html">Building Objects in GoJS</a>. Using
|
149 | <code>$</code> as an abbreviation for <code>go.GraphObject.make</code> is so
|
150 | handy that we will assume its use from now on. If you use <code>$</code> for
|
151 | something else in your code, you can always pick a different short variable
|
152 | name, such as <code>$$</code> or <code>MAKE</code> or <code>GO</code>.
|
153 | </p>
|
154 |
|
155 | <h2 id="DiagramsAndModels">Diagrams and Models</h2>
|
156 |
|
157 | <p>
|
158 | The Nodes and Links of a Diagram are visualizations of data that is managed by
|
159 | a Model.
|
160 | <b>GoJS</b> has a model-view architecture, where Models hold the data (arrays
|
161 | of JavaScript objects) that describe nodes and links, and Diagrams act as
|
162 | views to visualize this data using actual Node and Link objects. Models, not
|
163 | Diagrams, are what you load and then save after editing. You add whatever
|
164 | properties you need for your app on the data objects in the model; you do not
|
165 | add properties to or modify the prototype of the Diagram and GraphObject
|
166 | classes.
|
167 | </p>
|
168 |
|
169 | <p>
|
170 | Here's an example of a Model and Diagram, followed by the actual diagram it
|
171 | generates:
|
172 | </p>
|
173 |
|
174 | <pre class="lang-js"><code>
|
175 | var $ = go.GraphObject.make;
|
176 |
|
177 | var myDiagram =
|
178 | $(go.Diagram, "myDiagramDiv",
|
179 | { // enable Ctrl-Z to undo and Ctrl-Y to redo
|
180 | "undoManager.isEnabled": true
|
181 | });
|
182 |
|
183 | myDiagram.model = new go.Model(
|
184 | [ // for each object in this Array, the Diagram creates a Node to represent it
|
185 | { key: "Alpha" },
|
186 | { key: "Beta" },
|
187 | { key: "Gamma" }
|
188 | ]);
|
189 | </code></pre>
|
190 |
|
191 |
|
192 | <div id="myDiagramDiv2" class="diagramStyling" style="width: 400px; height: 150px"></div>
|
193 | <script>
|
194 | var $ = go.GraphObject.make;
|
195 |
|
196 | var myDiagram = $(go.Diagram, "myDiagramDiv2",
|
197 | {
|
198 | "undoManager.isEnabled": true,
|
199 | });
|
200 |
|
201 | myDiagram.model = new go.Model(
|
202 | [
|
203 | { key: "Alpha" },
|
204 | { key: "Beta" },
|
205 | { key: "Gamma" }
|
206 | ]);
|
207 | </script>
|
208 |
|
209 | <p>
|
210 | The diagram displays the three nodes that are in the model. Some interaction
|
211 | is already possible:
|
212 | </p>
|
213 | <ul>
|
214 | <li>
|
215 | Click and drag the background in the above diagram to pan the view.
|
216 | </li>
|
217 | <li>
|
218 | Click a node to select it, or press down on and drag a node to move it
|
219 | around.
|
220 | </li>
|
221 | <li>
|
222 | To create a selection box, click and hold on the background, then start
|
223 | dragging.
|
224 | </li>
|
225 | <li>
|
226 | Use Ctrl-C and Ctrl-V, or control-drag-and-drop, to make a copy of the selection.
|
227 | (Use Command key as the modifier on MacOS instead of the Control key.)
|
228 | </li>
|
229 | <li>
|
230 | Press the Delete key to delete selected nodes. (Read about more
|
231 | <a href="../intro/commands.html">Keyboard Commands</a>.)
|
232 | </li>
|
233 | <li>
|
234 | On touch devices, press and hold to bring up a context menu. (Read about
|
235 | <a href="../intro/contextMenus.html">Context Menus</a>.)
|
236 | </li>
|
237 | <li>
|
238 | Since the undo manager was enabled, Ctrl-Z and Ctrl-Y will undo and redo
|
239 | moves and copies and deletions.
|
240 | </li>
|
241 | </ul>
|
242 |
|
243 | <h2 id="StylingNodes">Styling Nodes</h2>
|
244 |
|
245 | <p>
|
246 | Nodes are styled by creating templates consisting of GraphObjects and setting
|
247 | properties on those objects. To create a
|
248 | <a href="../intro/nodes.html">Node</a>, we have several building block classes
|
249 | at our disposal:
|
250 | </p>
|
251 | <ul>
|
252 | <li>
|
253 | <a href="../intro/shapes.html">Shape</a>, to display pre-defined or custom
|
254 | geometry with colors
|
255 | </li>
|
256 | <li>
|
257 | <a href="../intro/textblocks.html">TextBlock</a>, to display (potentially
|
258 | editable) text in various fonts
|
259 | </li>
|
260 | <li>
|
261 | <a href="../intro/pictures.html">Picture</a>, to display images, including
|
262 | SVG files
|
263 | </li>
|
264 | <li>
|
265 | <a href="../intro/panels.html">Panel</a>, containers to hold a collection of
|
266 | other objects that can be positioned and sized in different manners
|
267 | according to the type of the Panel (like tables, vertical stacks, and
|
268 | stretching containers)
|
269 | </li>
|
270 | </ul>
|
271 |
|
272 | <p>
|
273 | All of these building blocks are derived from the
|
274 | <a href="../api/symbols/GraphObject.html">GraphObject</a> abstract class, so
|
275 | we casually refer to them as GraphObjects or objects or elements. Note that a
|
276 | GraphObject is <em>not</em> an HTML DOM element, so there is much less overhead in
|
277 | creating or modifying such objects.
|
278 | </p>
|
279 |
|
280 | <p>
|
281 | We want the model data properties to affect our Nodes, and this is done by way
|
282 | of data bindings. Data bindings allow us to change the appearance and behavior
|
283 | of GraphObjects in Nodes by automatically setting properties on those
|
284 | GraphObjects to values that are taken from the model data. The model data
|
285 | objects are plain JavaScript objects. You can choose to use whatever property
|
286 | names you like on the node data in the model.
|
287 | </p>
|
288 |
|
289 | <p>
|
290 | The default Node template is simple: A Node which contains one TextBlock.
|
291 | There is a data binding between a TextBlock's <code>text</code> property and
|
292 | the model data's <code>key</code> property. In code, the template looks
|
293 | something like this:
|
294 | </p>
|
295 |
|
296 | <pre class="lang-js"><code>
|
297 | myDiagram.nodeTemplate =
|
298 | $(go.Node,
|
299 | $(go.TextBlock,
|
300 | // TextBlock.text is bound to Node.data.key
|
301 | new go.Binding("text", "key"))
|
302 | );
|
303 | </code></pre>
|
304 | <p>
|
305 | TextBlocks, Shapes, and Pictures are the primitive building blocks of
|
306 | <b>GoJS</b>. TextBlocks cannot contain images; Shapes cannot contain text. If
|
307 | you want your node to show some text, you must use a TextBlock. If you want to
|
308 | draw or fill some geometrical figures, you must use a Shape.
|
309 | </p>
|
310 | <p>
|
311 | More generally, the skeleton of a Node template will look something like this:
|
312 | </p>
|
313 |
|
314 | <pre class="lang-js"><code>
|
315 | myDiagram.nodeTemplate =
|
316 | $(go.Node, "Vertical", // second argument of a Node (or any Panel) can be a Panel type
|
317 | /* set Node properties here */
|
318 | { // the Node.location point will be at the center of each node
|
319 | locationSpot: go.Spot.Center
|
320 | },
|
321 |
|
322 | /* add Bindings here */
|
323 | // example Node binding sets Node.location to the value of Node.data.loc
|
324 | new go.Binding("location", "loc"),
|
325 |
|
326 | /* add GraphObjects contained within the Node */
|
327 | // this Shape will be vertically above the TextBlock
|
328 | $(go.Shape,
|
329 | "RoundedRectangle", // string argument can name a predefined figure
|
330 | { /* set Shape properties here */ },
|
331 | // example Shape binding sets Shape.figure to the value of Node.data.fig
|
332 | new go.Binding("figure", "fig")),
|
333 |
|
334 | $(go.TextBlock,
|
335 | "default text", // string argument can be initial text string
|
336 | { /* set TextBlock properties here */ },
|
337 | // example TextBlock binding sets TextBlock.text to the value of Node.data.text
|
338 | new go.Binding("text"))
|
339 | );
|
340 | </code></pre>
|
341 |
|
342 | <p>
|
343 | The nesting of GraphObjects within Panels can be arbitrarily deep, and every
|
344 | class has its own unique set of properties to utilize, but this shows the
|
345 | general idea.
|
346 | </p>
|
347 |
|
348 | <p>
|
349 | Now that we have seen how to make a Node template, let's see a live example.
|
350 | We will make a simple template commonly seen in organizational diagrams — an
|
351 | image next to a name. Consider the following Node template:
|
352 | </p>
|
353 | <ul>
|
354 | <li>
|
355 | A Node of "Horizontal" Panel type, meaning that its elements will be laid
|
356 | out horizontally side-by-side. It has two elements:
|
357 | <ul>
|
358 | <li>A Picture for the portrait, with the image source data bound</li>
|
359 | <li>A TextBlock for the name, with the text data bound</li>
|
360 | </ul>
|
361 | </li>
|
362 | </ul>
|
363 |
|
364 | <pre class="lang-js"><code>
|
365 | var $ = go.GraphObject.make;
|
366 |
|
367 | var myDiagram =
|
368 | $(go.Diagram, "myDiagramDiv",
|
369 | { // enable Ctrl-Z to undo and Ctrl-Y to redo
|
370 | "undoManager.isEnabled": true
|
371 | });
|
372 |
|
373 | // define a simple Node template
|
374 | myDiagram.nodeTemplate =
|
375 | $(go.Node, "Horizontal",
|
376 | // the entire node will have a light-blue background
|
377 | { background: "#44CCFF" },
|
378 | $(go.Picture,
|
379 | // Pictures should normally have an explicit width and height.
|
380 | // This picture has a red background, only visible when there is no source set
|
381 | // or when the image is partially transparent.
|
382 | { margin: 10, width: 50, height: 50, background: "red" },
|
383 | // Picture.source is data bound to the "source" attribute of the model data
|
384 | new go.Binding("source")),
|
385 | $(go.TextBlock,
|
386 | "Default Text", // the initial value for TextBlock.text
|
387 | // some room around the text, a larger font, and a white stroke:
|
388 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
389 | // TextBlock.text is data bound to the "name" property of the model data
|
390 | new go.Binding("text", "name"))
|
391 | );
|
392 |
|
393 | myDiagram.model = new go.Model(
|
394 | [ // note that each node data object holds whatever properties it needs;
|
395 | // for this app we add the "name" and "source" properties
|
396 | { name: "Don Meow", source: "cat1.png" },
|
397 | { name: "Copricat", source: "cat2.png" },
|
398 | { name: "Demeter", source: "cat3.png" },
|
399 | { /* Empty node data */ }
|
400 | ]);
|
401 | </code></pre>
|
402 |
|
403 | <p>That code produces this diagram:</p>
|
404 |
|
405 |
|
406 | <div id="myDiagramDiv3" class="diagramStyling" style="width: 700px; height: 200px"></div>
|
407 | <script>
|
408 | var $ = go.GraphObject.make;
|
409 |
|
410 | var myDiagram =
|
411 | $(go.Diagram, "myDiagramDiv3",
|
412 | {
|
413 | "undoManager.isEnabled": true,
|
414 | });
|
415 |
|
416 |
|
417 | myDiagram.nodeTemplate =
|
418 | $(go.Node, "Horizontal",
|
419 |
|
420 | { background: "#44CCFF" },
|
421 | $(go.Picture,
|
422 |
|
423 |
|
424 |
|
425 | { margin: 10, width: 50, height: 50, background: "red" },
|
426 |
|
427 | new go.Binding("source")),
|
428 | $(go.TextBlock,
|
429 | "Default Text",
|
430 |
|
431 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
432 |
|
433 | new go.Binding("text", "name"))
|
434 | );
|
435 |
|
436 | myDiagram.model = new go.Model(
|
437 | [
|
438 |
|
439 |
|
440 | { name: "Don Meow", source: "cat1.png" },
|
441 | { name: "Copricat", source: "cat2.png" },
|
442 | { name: "Demeter", source: "cat3.png" },
|
443 | { }
|
444 | ]);
|
445 | </script>
|
446 |
|
447 | <p>
|
448 | We may want to show some "default" state when not all information is present,
|
449 | for instance when an image does not load or when a name is not known. The
|
450 | "empty" node data in this example is used to show that node templates can work
|
451 | perfectly well without any of the properties on the bound data.
|
452 | </p>
|
453 |
|
454 | <h2 id="KindsOfNodes">Kinds of Models</h2>
|
455 |
|
456 | <p>
|
457 | With a custom node template our diagram is becoming a pretty sight, but
|
458 | perhaps we want to show more. Perhaps we want an organizational chart to show
|
459 | that Don Meow is really the boss of a cat cartel. So we will create a complete
|
460 | organization chart diagram by adding some Links to show the relationship
|
461 | between individual nodes and a Layout to automatically position the nodes.
|
462 | </p>
|
463 |
|
464 | <p>
|
465 | In order to get links into our diagram, the basic <code>Model</code> is not
|
466 | going to cut it. We are going to have to pick one of the other two models in
|
467 | <b>GoJS</b>, both of which support Links. These are
|
468 | <code>GraphLinksModel</code> and <code>TreeModel</code>. (Read more about
|
469 | models <a href="../intro/usingModels.html">here</a>.)
|
470 | </p>
|
471 |
|
472 | <p>
|
473 | In GraphLinksModel, we have a <code>model.linkDataArray</code> in addition to
|
474 | the <code>model.nodeDataArray</code>. It holds an array of JavaScript objects,
|
475 | each describing a link by specifying the "to" and "from" node keys. Here's an
|
476 | example where node A links to node B and where node B links to node C:
|
477 | </p>
|
478 |
|
479 | <pre class="lang-js"><code>
|
480 | myDiagram.model = new go.GraphLinksModel(
|
481 | [ // the nodeDataArray
|
482 | { key: "A" },
|
483 | { key: "B" },
|
484 | { key: "C" }
|
485 | ],
|
486 | [ // the linkDataArray
|
487 | { from: "A", to: "B" },
|
488 | { from: "B", to: "C" }
|
489 | ]);
|
490 | </code></pre>
|
491 |
|
492 | <p>
|
493 | A GraphLinksModel allows you to have any number of links between nodes, going
|
494 | in any direction. There could be ten links running from A to B, and three more
|
495 | running the opposite way, from B to A.
|
496 | </p>
|
497 |
|
498 | <p>
|
499 | A TreeModel works a little differently. Instead of maintaining a separate
|
500 | array of link data, the links in a tree model are created by specifying a
|
501 | "parent" for a node data. Links are then created from this association. Here's
|
502 | the same example done as a TreeModel, with node A linking to node B and node B
|
503 | linking to node C:
|
504 | </p>
|
505 |
|
506 | <pre class="lang-js"><code>
|
507 | myDiagram.model = new go.TreeModel(
|
508 | [ // the nodeDataArray
|
509 | { key: "A" },
|
510 | { key: "B", parent: "A" },
|
511 | { key: "C", parent: "B" }
|
512 | ]);
|
513 | </code></pre>
|
514 |
|
515 | <p>
|
516 | TreeModel is simpler than GraphLinksModel, but it cannot make arbitrary link
|
517 | relationships, such as multiple links between the same two nodes, or having
|
518 | multiple parents. Our organizational diagram is a simple hierarchical
|
519 | tree-like structure, so we will choose TreeModel for this example.
|
520 | </p>
|
521 |
|
522 | <p>
|
523 | First, we will complete the data by adding a few more nodes, using a
|
524 | TreeModel, and specifying keys and parents in the data.
|
525 | </p>
|
526 |
|
527 | <pre class="lang-js"><code>
|
528 | var $ = go.GraphObject.make;
|
529 |
|
530 | var myDiagram =
|
531 | $(go.Diagram, "myDiagramDiv",
|
532 | { "undoManager.isEnabled": true });
|
533 |
|
534 | // the template we defined earlier
|
535 | myDiagram.nodeTemplate =
|
536 | $(go.Node, "Horizontal",
|
537 | { background: "#44CCFF" },
|
538 | $(go.Picture,
|
539 | { margin: 10, width: 50, height: 50, background: "red" },
|
540 | new go.Binding("source")),
|
541 | $(go.TextBlock, "Default Text",
|
542 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
543 | new go.Binding("text", "name"))
|
544 | );
|
545 |
|
546 | myDiagram.model = new go.TreeModel(
|
547 | [ // the "key" and "parent" property names are required,
|
548 | // but you can add whatever data properties you need for your app
|
549 | { key: "1", name: "Don Meow", source: "cat1.png" },
|
550 | { key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
551 | { key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
552 | { key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
553 | { key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
554 | { key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
555 | ]);
|
556 | </code></pre>
|
557 |
|
558 |
|
559 | <div id="myDiagramDiv4" class="diagramStyling" style="width: 700px; height: 200px"></div>
|
560 | <script>
|
561 | var $ = go.GraphObject.make;
|
562 |
|
563 | var myDiagram =
|
564 | $(go.Diagram, "myDiagramDiv4",
|
565 | { "undoManager.isEnabled": true });
|
566 |
|
567 |
|
568 | myDiagram.nodeTemplate =
|
569 | $(go.Node, "Horizontal",
|
570 | { background: "#44CCFF" },
|
571 | $(go.Picture,
|
572 | { margin: 10, width: 50, height: 50, background: "red" },
|
573 | new go.Binding("source")),
|
574 | $(go.TextBlock, "Default Text",
|
575 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
576 | new go.Binding("text", "name"))
|
577 | );
|
578 |
|
579 | myDiagram.model = new go.TreeModel(
|
580 | [
|
581 |
|
582 | { key: "1", name: "Don Meow", source: "cat1.png" },
|
583 | { key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
584 | { key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
585 | { key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
586 | { key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
587 | { key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" },
|
588 | ]);
|
589 | </script>
|
590 |
|
591 | <h2 id="DiagramLayouts">Diagram Layouts</h2>
|
592 |
|
593 | <p>
|
594 | As you can see the TreeModel automatically creates the necessary Links to
|
595 | associate the Nodes, but it's hard to tell whose parent is who.
|
596 | </p>
|
597 |
|
598 | <p>
|
599 | Diagrams have a default layout which takes all nodes that do not have a
|
600 | location and gives them locations, arranging them in a grid. We could
|
601 | explicitly give each of our nodes a location to sort out this organizational
|
602 | mess, but as an easier solution in our case, we will use a layout that gives
|
603 | us good locations automatically.
|
604 | </p>
|
605 |
|
606 | <p>
|
607 | We want to show a hierarchy, and are already using a TreeModel, so the most
|
608 | natural layout choice is TreeLayout. TreeLayout defaults to flowing from left
|
609 | to right, so to get it to flow from top to bottom (as is common in
|
610 | organizational diagrams), we will set the <code>angle</code> property to 90.
|
611 | </p>
|
612 |
|
613 | <p>
|
614 | Using layouts in <b>GoJS</b> is usually simple. Each kind of layout has a
|
615 | number of properties that affect the results. There are samples for each
|
616 | layout (like <a href="../samples/tLayout.html">TreeLayout Demo</a>) that
|
617 | showcase its properties.
|
618 | </p>
|
619 |
|
620 | <pre class="lang-js"><code>
|
621 | // define a TreeLayout that flows from top to bottom
|
622 | myDiagram.layout =
|
623 | $(go.TreeLayout,
|
624 | { angle: 90, layerSpacing: 35 });
|
625 | </code></pre>
|
626 |
|
627 | <p>
|
628 | <b>GoJS</b> has many other layouts, which you can read about
|
629 | <a href="../intro/layouts.html">here</a>.
|
630 | </p>
|
631 |
|
632 | <p>
|
633 | Adding the layout to the diagram and model so far, we can see our results:
|
634 | </p>
|
635 |
|
636 | <pre class="lang-js"><code>
|
637 | var $ = go.GraphObject.make;
|
638 |
|
639 | var myDiagram =
|
640 | $(go.Diagram, "myDiagramDiv",
|
641 | {
|
642 | "undoManager.isEnabled": true,
|
643 | layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
|
644 | { angle: 90, layerSpacing: 35 })
|
645 | });
|
646 |
|
647 | // the template we defined earlier
|
648 | myDiagram.nodeTemplate =
|
649 | $(go.Node, "Horizontal",
|
650 | { background: "#44CCFF" },
|
651 | $(go.Picture,
|
652 | { margin: 10, width: 50, height: 50, background: "red" },
|
653 | new go.Binding("source")),
|
654 | $(go.TextBlock, "Default Text",
|
655 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
656 | new go.Binding("text", "name"))
|
657 | );
|
658 |
|
659 | // the same model as before
|
660 | myDiagram.model = new go.TreeModel(
|
661 | [
|
662 | { key: "1", name: "Don Meow", source: "cat1.png" },
|
663 | { key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
664 | { key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
665 | { key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
666 | { key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
667 | { key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
668 | ]);
|
669 | </code></pre>
|
670 |
|
671 |
|
672 | <div id="myDiagramDiv5" class="diagramStyling" style="width: 700px; height: 400px"></div>
|
673 | <script>
|
674 | var $ = go.GraphObject.make;
|
675 |
|
676 | var myDiagram =
|
677 | $(go.Diagram, "myDiagramDiv5",
|
678 | {
|
679 | "undoManager.isEnabled": true,
|
680 | layout: $(go.TreeLayout,
|
681 | { angle: 90, layerSpacing: 35 }),
|
682 | });
|
683 |
|
684 |
|
685 | myDiagram.nodeTemplate =
|
686 | $(go.Node, "Horizontal",
|
687 | { background: "#44CCFF" },
|
688 | $(go.Picture,
|
689 | { margin: 10, width: 50, height: 50, background: "red" },
|
690 | new go.Binding("source")),
|
691 | $(go.TextBlock, "Default Text",
|
692 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
693 | new go.Binding("text", "name"))
|
694 | );
|
695 |
|
696 |
|
697 | myDiagram.model = new go.TreeModel(
|
698 | [
|
699 | { key: "1", name: "Don Meow", source: "cat1.png" },
|
700 | { key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
701 | { key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
702 | { key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
703 | { key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
704 | { key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" },
|
705 | ]);
|
706 | </script>
|
707 |
|
708 | <p>
|
709 | Our diagram is starting to look like a proper organization chart, but we could
|
710 | do better with the links.
|
711 | </p>
|
712 |
|
713 | <h2 id="LinkTemplates">Link Templates</h2>
|
714 |
|
715 | <p>
|
716 | We will construct a new Link template that will better suit our wide, boxy
|
717 | nodes. A <a href="../intro/links.html">Link</a> is a different kind of Part,
|
718 | not like a Node. The main element of a Link is the Link's shape, and must be a
|
719 | Shape that will have its geometry computed dynamically by <b>GoJS</b>. Our
|
720 | link is going to consist of just this shape, with its stroke a little thicker
|
721 | than normal and dark gray instead of black. Unlike the default link template
|
722 | we will not have an arrowhead. And we will change the Link
|
723 | <code>routing</code> property from Normal to Orthogonal, and give it a
|
724 | <code>corner</code> value so that right-angle turns are rounded.
|
725 | </p>
|
726 |
|
727 | <pre class="lang-js"><code>
|
728 | // define a Link template that routes orthogonally, with no arrowhead
|
729 | myDiagram.linkTemplate =
|
730 | $(go.Link,
|
731 | // default routing is go.Link.Normal
|
732 | // default corner is 0
|
733 | { routing: go.Link.Orthogonal, corner: 5 },
|
734 | // the link path, a Shape
|
735 | $(go.Shape, { strokeWidth: 3, stroke: "#555" })
|
736 |
|
737 | // if we wanted an arrowhead we would also add another Shape with toArrow defined:
|
738 | // $(go.Shape, { toArrow: "Standard", stroke: null }
|
739 | );
|
740 | </code></pre>
|
741 |
|
742 | <p>
|
743 | Combining our Link template with our Node template, TreeModel, and TreeLayout,
|
744 | we finally have a full organization diagram. The complete code is repeated
|
745 | below, and the resulting diagram follows:
|
746 | </p>
|
747 |
|
748 | <pre class="lang-js"><code>
|
749 | var $ = go.GraphObject.make;
|
750 |
|
751 | var myDiagram =
|
752 | $(go.Diagram, "myDiagramDiv",
|
753 | {
|
754 | "undoManager.isEnabled": true,
|
755 | layout: $(go.TreeLayout,
|
756 | { angle: 90, layerSpacing: 35 })
|
757 | });
|
758 |
|
759 | myDiagram.nodeTemplate =
|
760 | $(go.Node, "Horizontal",
|
761 | { background: "#44CCFF" },
|
762 | $(go.Picture,
|
763 | { margin: 10, width: 50, height: 50, background: "red" },
|
764 | new go.Binding("source")),
|
765 | $(go.TextBlock, "Default Text",
|
766 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
767 | new go.Binding("text", "name"))
|
768 | );
|
769 |
|
770 | // define a Link template that routes orthogonally, with no arrowhead
|
771 | myDiagram.linkTemplate =
|
772 | $(go.Link,
|
773 | { routing: go.Link.Orthogonal, corner: 5 },
|
774 | $(go.Shape, // the link's path shape
|
775 | { strokeWidth: 3, stroke: "#555" })
|
776 | );
|
777 |
|
778 | // it's best to declare all templates before assigning the model
|
779 | myDiagram.model = new go.TreeModel(
|
780 | [
|
781 | { key: "1", name: "Don Meow", source: "cat1.png" },
|
782 | { key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
783 | { key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
784 | { key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
785 | { key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
786 | { key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
787 | ]);
|
788 | </code></pre>
|
789 |
|
790 |
|
791 | <div id="myDiagramDiv6" class="diagramStyling" style="width: 700px; height: 400px"></div>
|
792 | <script>
|
793 | var $ = go.GraphObject.make;
|
794 |
|
795 | var myDiagram =
|
796 | $(go.Diagram, "myDiagramDiv6",
|
797 | {
|
798 | "undoManager.isEnabled": true,
|
799 | layout: $(go.TreeLayout,
|
800 | { angle: 90, layerSpacing: 35 }),
|
801 | });
|
802 |
|
803 | myDiagram.nodeTemplate =
|
804 | $(go.Node, "Horizontal",
|
805 | { background: "#44CCFF" },
|
806 | $(go.Picture,
|
807 | { margin: 10, width: 50, height: 50, background: "red" },
|
808 | new go.Binding("source")),
|
809 | $(go.TextBlock, "Default Text",
|
810 | { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
811 | new go.Binding("text", "name"))
|
812 | );
|
813 |
|
814 |
|
815 | myDiagram.linkTemplate =
|
816 | $(go.Link,
|
817 | { routing: go.Link.Orthogonal, corner: 5 },
|
818 | $(go.Shape,
|
819 | { strokeWidth: 3, stroke: "#555" })
|
820 | );
|
821 |
|
822 |
|
823 | myDiagram.model = new go.TreeModel(
|
824 | [
|
825 | { key: "1", name: "Don Meow", source: "cat1.png" },
|
826 | { key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
827 | { key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
828 | { key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
829 | { key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
830 | { key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" },
|
831 | ]);
|
832 | </script>
|
833 |
|
834 | <h2 id="LearnMore">Learn More</h2>
|
835 | <p>
|
836 | You may want to read more tutorials, such as the
|
837 | <a href="graphObject.html">GraphObject Manipulation</a> tutorial and the
|
838 | <a href="interactivity.html">Interactivity</a> tutorial. You can also watch
|
839 | tutorials on
|
840 | <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">YouTube</a
|
841 | >.
|
842 | </p>
|
843 | <p>
|
844 | Also consider looking at the <a href="../samples/index.html">samples</a> to
|
845 | see some of the diagrams possible with <b>GoJS</b>, or read the
|
846 | <a href="../intro/index.html">technical introduction</a> to get an in-depth
|
847 | look at the components of <b>GoJS</b>.
|
848 | </p>
|
849 |
|
850 |
|
851 |
|
852 | </div>
|
853 | </div>
|
854 |
|
855 | <div class="bg-nwoods-primary">
|
856 | <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
|
857 | <p id="version" class="leading-none mb-2 my-4">GoJS</p>
|
858 | </section>
|
859 | </div><footer class="bg-nwoods-primary text-white">
|
860 | <div class="container max-w-screen-lg mx-auto px-8">
|
861 | <div class="w-full py-6">
|
862 |
|
863 | <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
|
864 | <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
|
865 | <li class="list-none row-span-2">
|
866 | <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
|
867 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
868 | <li>
|
869 | <a href="../samples/index.html">Samples</a>
|
870 | </li>
|
871 | <li>
|
872 | <a href="../learn/index.html">Learn</a>
|
873 | </li>
|
874 | <li>
|
875 | <a href="../intro/index.html">Intro</a>
|
876 | </li>
|
877 | <li>
|
878 | <a href="../api/index.html">API</a>
|
879 | </li>
|
880 | <li>
|
881 | <a href="../changelog.html">Changelog</a>
|
882 | </li>
|
883 | <li>
|
884 | <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
|
885 | </li>
|
886 | </ul>
|
887 | </li>
|
888 | <li class="list-none row-span-2">
|
889 | <h2 class="text-base font-semibold tracking-wide">Support</h2>
|
890 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
891 | <li>
|
892 | <a href="https://www.nwoods.com/contact.html"
|
893 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
|
894 | </li>
|
895 | <li>
|
896 | <a href="https://forum.nwoods.com/c/gojs">Forum</a>
|
897 | </li>
|
898 | <li>
|
899 | <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
|
900 | </li>
|
901 | <li>
|
902 | <a href="https://www.nwoods.com/sales/index.html"
|
903 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
|
904 | </li>
|
905 | <li>
|
906 | <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
|
907 | </li>
|
908 | </ul>
|
909 | </li>
|
910 | <li class="list-none row-span-2">
|
911 | <h2 class="text-base font-semibold tracking-wide">Company</h2>
|
912 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
913 | <li>
|
914 | <a href="https://www.nwoods.com">Northwoods</a>
|
915 | </li>
|
916 | <li>
|
917 | <a href="https://www.nwoods.com/about.html">About Us</a>
|
918 | </li>
|
919 | <li>
|
920 | <a href="https://www.nwoods.com/contact.html">Contact Us</a>
|
921 | </li>
|
922 | <li>
|
923 | <a href="https://twitter.com/northwoodsgo">Twitter</a>
|
924 | </li>
|
925 |
|
926 | </ul>
|
927 | </li>
|
928 | </ul>
|
929 |
|
930 |
|
931 | <p class="text-sm text-gray-100 md:mb-6">
|
932 | Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
|
933 | </p>
|
934 | </div>
|
935 | </div>
|
936 | </footer> </body>
|
937 |
|
938 | <script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
|
939 | <script>
|
940 | window.dataLayer = window.dataLayer || [];
|
941 | function gtag(){dataLayer.push(arguments);}
|
942 | gtag('js', new Date()); gtag('config', 'UA-1506307-5');
|
943 | var getOutboundLink = function(url, label) {
|
944 | gtag('event', 'click', {
|
945 | 'event_category': 'outbound',
|
946 | 'event_label': label,
|
947 | 'transport_type': 'beacon'
|
948 | });
|
949 | }
|
950 |
|
951 |
|
952 | var topButton = document.getElementById("topnavButton");
|
953 | var topnavList = document.getElementById("topnavList");
|
954 | topButton.addEventListener("click", function() {
|
955 | this.classList.toggle("active");
|
956 | topnavList.classList.toggle("hidden");
|
957 | document.getElementById("topnavOpen").classList.toggle("hidden");
|
958 | document.getElementById("topnavClosed").classList.toggle("hidden");
|
959 | });
|
960 | </script>
|
961 | <script src="../assets/js/prism.js"></script>
|
962 | <script src="../assets/js/goDoc.js"></script>
|
963 | <script>
|
964 | document.addEventListener("DOMContentLoaded", function() {
|
965 | if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
|
966 | if (window.goDoc) window.goDoc();
|
967 | });
|
968 | </script>
|
969 | </html> |
\ | No newline at end of file |