UNPKG

26.5 kBHTMLView Raw
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<!-- Copyright 1998-2021 by Northwoods Software Corporation. --> <title> GoJS Pictures -- 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 &amp; 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>Pictures</h1>
137<p>
138Use the <a>Picture</a> class to display images.
139The most common usage is to set the <a>Picture.source</a> property with a URL string,
140along with the <a>GraphObject.desiredSize</a> or the <a>GraphObject.width</a> and <a>GraphObject.height</a>.
141</p>
142<p>
143If the URL is just a simple constant string, you can pass the string directly as an argument to <a>GraphObject,make</a>,
144rather than assign the "source:" property. Both techniques have the same effect.
145</p>
146<p>
147In these simplistic demonstrations, the code programmatically creates a Part and adds it to the Diagram.
148Once you learn about models and data binding you will generally not create parts (nodes or links) programmatically.
149</p>
150<pre class="lang-js" id="source"><code>
151 diagram.add(
152 $(go.Part,
153 $(go.Picture, "images/100x65.png")
154 ));
155</code></pre>
156<script>goCode("source", 600, 160)</script>
157<p>
158However for more sophisticated control you can set the <a>Picture.element</a>
159to an <b>HTMLImageElement</b> or an <b>HTMLCanvasElement</b>.
160</p>
161
162<h3 id="SimpleIconsUsingFonts">Simple Icons Using Fonts</h3>
163<p>
164 Note: for showing simple icons you may want to use an icon font.
165 See the example using a <a>TextBlock</a> rather than a <a>Picture</a> at:
166 <a href="textBlocks.html#IconFonts">Icon Fonts</a>
167</p>
168
169<h2 id="Sizing">Sizing</h2>
170<p>
171If you do not set the <a>GraphObject.desiredSize</a> of a <a>Picture</a>, it will get the picture's natural size.
172But when you set the desiredSize to be something different than the natural size, the picture may be stretched or compressed to fit.
173</p>
174<p>
175The following pictures all show a picture of kittens that is 100x65 pixels.
176</p>
177<ul>
178<li>The first picture shows the image at its natural size.</li>
179<li>The second picture also shows the image at its natural size, but has its desiredSize set explicitly.</li>
180<li>The third picture increases the size of the Picture, causing the image to be expanded evenly.</li>
181<li>The fourth picture squeezes the 100x65 image into a 50x32.5 space -- half size.
182This also maintains the original aspect ratio of the image.</li>
183<li>The last picture sets the picture size to be 50x70, which changes the aspect ratio to be taller and thinner than the original.</li>
184</ul>
185<pre class="lang-js" id="sizedPictures"><code>
186 diagram.add(
187 $(go.Part, "Table",
188 $(go.Picture, { source: "images/100x65.png", column: 0,
189 margin: 2 }),
190 $(go.TextBlock, "natural", { row: 1, column: 0 }),
191 $(go.Picture, { source: "images/100x65.png", column: 1,
192 width: 100, height: 65, margin: 2 }),
193 $(go.TextBlock, "same size", { row: 1, column: 1 }),
194 $(go.Picture, { source: "images/100x65.png", column: 2,
195 width: 200, height: 130, margin: 2 }),
196 $(go.TextBlock, "bigger", { row: 1, column: 2 }),
197 $(go.Picture, { source: "images/100x65.png", column: 3,
198 width: 50, height: 32.5, margin: 2 }),
199 $(go.TextBlock, "smaller", { row: 1, column: 3 }),
200 $(go.Picture, { source: "images/100x65.png", column: 4,
201 width: 50, height: 70, margin: 2 }),
202 $(go.TextBlock, "stretched", { row: 1, column: 4 })
203 ));
204</code></pre>
205<script>goCode("sizedPictures", 600, 160)</script>
206<p>
207Note that it may take a while for the media to load.
208Until the time that the media has loaded sufficiently to know its natural size, the Picture may have the wrong size, such as 0x0.
209We recommend that you specify the desiredSize (or width and height) so that
210the Panel(s) holding the Picture will not have to rearrange themselves once the media has loaded.
211</p>
212<p>
213However for the times when you cannot know the natural size ahead of time, there are alternative ways of stretching images to fit in a given space.
214</p>
215
216<h2 id="ImageStretch">Image Stretch</h2>
217<p>
218Instead of always stretching or compressing to fill the desiredSize,
219you can set the <a>Picture.imageStretch</a> property to control the size and aspect ratio of the drawn image.
220</p>
221<p>
222The following pictures demonstrate the four possible values for Picture.imageStretch.
223All four Pictures here have the size 60x80 and show the same 100x65 PNG file.
224The Pictures also have a light green background, to show the space available that may be left unused, but is still part of the Picture's bounds.
225</p>
226<ul>
227<li>The first picture demonstrates the default behavior, to stretch in both directions.
228Note how the image is distorted to be narrower than it should be.
229However, all of the image is shown.
230Because the image fills the whole area and the image is not translucent, the background color does not show anywhere.
231</li>
232<li>You can see in the second picture, using an imageStretch of <a>GraphObject,None</a>,
233how it only shows a fraction of the whole kitten image.
234Because the desiredSize is smaller than the natural size of the image,
235parts of the image are clipped.
236</li>
237<li>The third picture shows how a <a>GraphObject,Uniform</a> imageStretch will make sure that all of the image is shown,
238at the expense of reducing the scale and leaving some empty space at the sides or at the top and bottom.
239In this case, because the natural image aspect ratio is wider than the available 60x80 aspect ratio,
240the empty space will be at the top and bottom.
241</li>
242<li>The fourth picture shows how a <a>GraphObject,UniformToFill</a> imageStretch will ensure that the whole area is occupied
243with image, but that not all of the image is shown, since some may be clipped at the sides or at the top and bottom.
244Such images normally have a larger scale than when using Uniform imageStretch.
245In this case what must be clipped is at the sides of the image.
246</li>
247<li>Finally there is a separate Part containing the original image, sized naturally, for comparison.</li>
248</ul>
249<pre class="lang-js" id="stretchedPictures"><code>
250 diagram.add(
251 $(go.Part, "Table",
252 $(go.Picture, "images/100x65.png",
253 { column: 0, width: 60, height: 80, margin: 2, background: "chartreuse",
254 imageStretch: go.GraphObject.Fill }),
255 $(go.TextBlock, "Fill", { row: 1, column: 0 }),
256 $(go.Picture, "images/100x65.png",
257 { column: 1, width: 60, height: 80, margin: 2, background: "chartreuse",
258 imageStretch: go.GraphObject.None }),
259 $(go.TextBlock, "None", { row: 1, column: 1 }),
260 $(go.Picture, "images/100x65.png",
261 { column: 2, width: 60, height: 80, margin: 2, background: "chartreuse",
262 imageStretch: go.GraphObject.Uniform }),
263 $(go.TextBlock, "Uniform", { row: 1, column: 2 }),
264 $(go.Picture, "images/100x65.png",
265 { column: 3, width: 60, height: 80, margin: 2, background: "chartreuse",
266 imageStretch: go.GraphObject.UniformToFill }),
267 $(go.TextBlock, "UniformToFill", { row: 1, column: 3 })
268 ));
269
270 // The original image sized naturally, for comparison
271 diagram.add(
272 $(go.Part, "Vertical",
273 $(go.Picture, "images/100x65.png"),
274 $(go.TextBlock, "Original image,\nsized naturally")
275 ));
276</code></pre>
277<script>goCode("stretchedPictures", 600, 120)</script>
278<p>
279 When images are clipped you can control what part of the image is drawn by using the <a>Picture.imageAlignment</a> property.
280</p>
281
282<h2 id="Clipping">Clipping</h2>
283
284<p>
285 If you have a Picture that must be clipped to a geometry, such as to produce a circular image, there are two options.
286 The first is to use a "frame" geometry to hide part of the image.
287 Typically this frame is the same color as the Diagram background or the background of the Node.
288 This method does not change the area of the Picture, does not allow for true transparency, and clicking anywhere in the bounds will always pick the picture.
289</p>
290<p>
291 A second method uses <a>Panel.isClipping</a>.
292 This property on a "Spot" Panel allows the filled area of the main Shape to serve as a clipping region instead of a drawn shape.
293 This method does not change the area of the Picture, but does allow for transparency
294 It affects object picking so that only the resultant drawn area is pickable; areas of the image that are not drawn cannot be "hit".
295</p>
296<p>
297 Examples of both follow:
298</p>
299<pre class="lang-js" id="clipPictures"><code>
300
301 diagram.layout = $(go.GridLayout);
302
303 // Using a black "frame" geometry to hide part of the image.
304 // Typically this frame is the same color as the Diagram background or the background of the Node.
305 diagram.add(
306 $(go.Part, "Spot",
307 { scale: 2 },
308 $(go.Picture, "../samples/images/55x55.png",
309 {
310 name: 'Picture',
311 desiredSize: new go.Size(55, 55),
312 background: 'red'
313 }
314 ),
315 $(go.Shape,
316 {
317 strokeWidth: 0,
318 stroke: null,
319 geometryString: "f M0 0 L100 0 L100 100 L0 100 z M5,50a45,45 0 1,0 90,0a45,45 0 1,0 -90,0 z",
320 width: 56,
321 height: 56,
322 fill: 'black'
323 })
324 )
325 );
326
327 // Using Panel.isClipping
328 diagram.add(
329 $(go.Part, "Spot",
330 { isClipping: true, scale: 2 },
331 $(go.Shape, "Circle", { width: 55, strokeWidth: 0 } ),
332 $(go.Picture, "../samples/images/55x55.png",
333 { width: 55, height: 55 }
334 )
335 )
336 );
337
338 // Using Panel.isClipping and also having a surrounding panel
339 diagram.add(
340 $(go.Part, "Spot",
341 { scale: 2 },
342 $(go.Shape, "Circle", { width: 65, strokeWidth: 0, fill: 'red' } ),
343 $(go.Panel, "Spot",
344 { isClipping: true },
345 $(go.Shape, "Circle", { width: 55, strokeWidth: 0 } ),
346 $(go.Picture, "../samples/images/55x55.png",
347 { width: 55, height: 55 }
348 )
349 )
350 )
351 );
352</code></pre>
353<script>goCode("clipPictures", 500, 200)</script>
354
355
356<h2 id="Flipping">Flipping</h2>
357
358<p>
359 You can flip image sources horizontally and vertically with the <a>Picture.flip</a> property:
360</p>
361
362<pre class="lang-js" id="flipPictures"><code>
363 diagram.add(
364 $(go.Part, "Table",
365 $(go.Picture, { source: "images/100x65.png", column: 0, margin: 2,
366 flip: go.GraphObject.None
367 }),
368 $(go.TextBlock, "None (default)", { row: 1, column: 0 }),
369 $(go.Picture, { source: "images/100x65.png", column: 1, margin: 2,
370 flip: go.GraphObject.FlipHorizontal
371 }),
372 $(go.TextBlock, "FlipHorizontal", { row: 1, column: 1 }),
373 $(go.Picture, { source: "images/100x65.png", column: 2, margin: 2,
374 flip: go.GraphObject.FlipVertical
375 }),
376 $(go.TextBlock, "FlipVertical", { row: 1, column: 2 }),
377 $(go.Picture, { source: "images/100x65.png", column: 3, margin: 2,
378 flip: go.GraphObject.FlipBoth
379 }),
380 $(go.TextBlock, "FlipBoth", { row: 1, column: 3 })
381 ));
382</code></pre>
383<script>goCode("flipPictures", 600, 160)</script>
384
385<h2 id="CrossOriginPictures">Cross Origin Pictures</h2>
386
387<p>
388 Since Pictures are backed by HTMLImageElements, they must abide by the same Cross-origin (CORS) rules that apply to Images.
389 If you are using images that apply to CORS rules, you may need to set the <a>Picture.sourceCrossOrigin</a> property to a function that returns an appropriate value.
390 If <code>sourceCrossOrigin</code> is supplied, the value returned by the function is used as the value of any constructed <code>image.crossOrigin</code>.
391 Example:
392</p>
393<pre class="lang-js"><code>
394 $(go.Picture,
395 { width: 64, height: 64 },
396 { sourceCrossOrigin: function(pict) { return "use-credentials"; } },
397 new go.Binding("source", "path"))
398</code></pre>
399<p>
400 Common values to return are "use-credentials" and "anonymous", but other situations may call for other values or conditional values.
401 We suggest researching <a href="https://enable-cors.org/">cross-origin resource sharing</a> to determine what is right for your situation.
402</p>
403<p>
404 If you are using <a>Diagram.makeImage</a>, <a>Diagram.makeImageData</a>, or <a>Diagram.makeSvg</a>,
405 and you are seeing blank or missing images, CORS-related problems are the first thing to investigate.
406</p>
407<h2 id="UsingSVGAsPictureSource">Using SVG as a Picture source</h2>
408
409<p>
410 Almost all browsers accept SVG files as a Picture source, but in many browsers you <strong>must</strong>:
411</p>
412<ul>
413 <li>Assign width and height attributes to the SVG element. These values should be integers. (necessary for Firefox)</li>
414 <li>Assign the Picture element a desired size, which <strong>must</strong> be the same as its width and height attributes (necessary for Internet Explorer).</li>
415</ul>
416<p>
417 This first SVG element has a width and height specified in its SVG element, and also has its desired size set. It should display in most browsers:
418</p>
419
420<pre class="lang-html"><code>
421&lt;svg xmlns="http://www.w3.org/2000/svg"
422 xmlns:xlink="http://www.w3.org/1999/xlink"
423 width="580" height="580"&gt;
424 ...
425</code></pre>
426
427<pre class="lang-js" id="svg1"><code>
428 diagram.add(
429 $(go.Part,
430 $(go.Picture, { desiredSize: new go.Size(580, 580), source: "images/tiger.svg" })
431 ));
432 diagram.scale = 0.5;
433</code></pre>
434<script>goCode("svg1", 300, 300)</script>
435
436<p style="color: red;"><strong>
437 This SVG element does not specify width and height attributes in its SVG element, and as a result some browsers may not render it:
438</strong></p>
439
440<pre class="lang-html"><code>
441&lt;svg xmlns="http://www.w3.org/2000/svg"
442 xmlns:xlink="http://www.w3.org/1999/xlink"&gt;
443 ...
444</code></pre>
445<pre class="lang-js" id="svg2"><code>
446 diagram.add(
447 $(go.Part,
448 $(go.Picture, { source: "images/tiger-noWidthHeightSpecified.svg" })
449 ));
450 diagram.scale = 0.5;
451</code></pre>
452<script>goCode("svg2", 300, 300)</script>
453
454 </div>
455 </div>
456
457 <div class="bg-nwoods-primary">
458 <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
459 <p id="version" class="leading-none mb-2 my-4">GoJS</p>
460 </section>
461 </div><footer class="bg-nwoods-primary text-white">
462 <div class="container max-w-screen-lg mx-auto px-8">
463 <div class="w-full py-6">
464
465 <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
466 <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
467 <li class="list-none row-span-2">
468 <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
469 <ul class="list-none space-y-4 md:space-y-1 px-0">
470 <li>
471 <a href="../samples/index.html">Samples</a>
472 </li>
473 <li>
474 <a href="../learn/index.html">Learn</a>
475 </li>
476 <li>
477 <a href="../intro/index.html">Intro</a>
478 </li>
479 <li>
480 <a href="../api/index.html">API</a>
481 </li>
482 <li>
483 <a href="../changelog.html">Changelog</a>
484 </li>
485 <li>
486 <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
487 </li>
488 </ul>
489 </li>
490 <li class="list-none row-span-2">
491 <h2 class="text-base font-semibold tracking-wide">Support</h2>
492 <ul class="list-none space-y-4 md:space-y-1 px-0">
493 <li>
494 <a href="https://www.nwoods.com/contact.html"
495 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
496 </li>
497 <li>
498 <a href="https://forum.nwoods.com/c/gojs">Forum</a>
499 </li>
500 <li>
501 <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
502 </li>
503 <li>
504 <a href="https://www.nwoods.com/sales/index.html"
505 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
506 </li>
507 <li>
508 <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
509 </li>
510 </ul>
511 </li>
512 <li class="list-none row-span-2">
513 <h2 class="text-base font-semibold tracking-wide">Company</h2>
514 <ul class="list-none space-y-4 md:space-y-1 px-0">
515 <li>
516 <a href="https://www.nwoods.com">Northwoods</a>
517 </li>
518 <li>
519 <a href="https://www.nwoods.com/about.html">About Us</a>
520 </li>
521 <li>
522 <a href="https://www.nwoods.com/contact.html">Contact Us</a>
523 </li>
524 <li>
525 <a href="https://twitter.com/northwoodsgo">Twitter</a>
526 </li>
527
528 </ul>
529 </li>
530 </ul>
531
532
533 <p class="text-sm text-gray-100 md:mb-6">
534 Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
535 </p>
536 </div>
537 </div>
538</footer> </body>
539
540<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
541<script>
542 window.dataLayer = window.dataLayer || [];
543 function gtag(){dataLayer.push(arguments);}
544 gtag('js', new Date()); gtag('config', 'UA-1506307-5');
545 var getOutboundLink = function(url, label) {
546 gtag('event', 'click', {
547 'event_category': 'outbound',
548 'event_label': label,
549 'transport_type': 'beacon'
550 });
551 }
552
553 // topnav
554 var topButton = document.getElementById("topnavButton");
555 var topnavList = document.getElementById("topnavList");
556 topButton.addEventListener("click", function() {
557 this.classList.toggle("active");
558 topnavList.classList.toggle("hidden");
559 document.getElementById("topnavOpen").classList.toggle("hidden");
560 document.getElementById("topnavClosed").classList.toggle("hidden");
561 });
562</script>
563 <script src="../assets/js/prism.js"></script>
564 <script src="../release/go.js"></script>
565 <script src="../assets/js/goDoc.js"></script>
566 <script>
567 document.addEventListener("DOMContentLoaded", function() {
568 if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
569 if (window.goDoc) window.goDoc();
570 var d = window.diagrams;
571 for (var i = 0; i < d.length; i++) {
572 var dargs = d[i];
573 goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
574 }
575 if (window.extra) window.extra();
576 });
577 </script>
578</html>