UNPKG

39.3 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 Animation -- 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<h1>GoJS Animation</h1>
135<p>
136 <b>GoJS</b> offers several built-in animations, enabled by default, as well as the ability to create arbitrary animations.
137</p>
138<p>
139 The <a>Diagram.animationManager</a> handles animations within a <a>Diagram</a>.
140 The <a>AnimationManager</a> automatically sets up and dispatches default animations, and has properties to customize and disable them.
141 Custom animations are possible by creating instances of <a>Animation</a> or <a>AnimationTrigger</a>.
142</p>
143
144<div class="box" style="background-color: lightgoldenrodyellow; padding: 10px;">
145 <p>This introduction page details the different classes used for GoJS animation.</p>
146 <p>To see more demonstrations of custom animations, visit the <a href="../samples/customAnimations.html">Custom Animations extension sample</a>.</p>
147</div>
148
149
150<h2 id="DefaultAnimations">Default Animations</h2>
151
152<p>
153 By default, the AnimationManager creates and runs several animations for its Diagram using a single
154 instance of Animation, the <a>AnimationManager.defaultAnimation</a>.
155 These animations occur on various commands, by the <a>Diagram.model</a> setter, and upon layouts.
156 Unlike other Animations, they will be stopped if a new transaction is started during animation.
157</p>
158<p>
159 GoJS will begin an animation automatically for these reasons:
160</p>
161
162<p>Invoked by <a>CommandHandler</a>:</p>
163<ul>
164 <li>"Collapse SubGraph" - Animates the collapsing nodes by "disappearing" them, animating their scales and positions into their group.
165 <li>"Expand SubGraph" - Expands groups by animating the scales and positions of nodes starting within the collapsed group.
166 <li>"Collapse Tree" - Animates the collapsing nodes by "disappearing" them, animating their scales and positions into the root node.
167 <li>"Expand Tree" - Expands subtrees by animating the scales and positions of descendant nodes starting within the collapsed root node.
168 <li>"Scroll To Part" - Animates the <a>Diagram.position</a> and may expand groups or expand subtrees to make the node visible.
169 <li>"Zoom To Fit" - Animates the <a>Diagram.position</a> and <a>Diagram.scale</a>.
170</ul>
171
172<p>Invoked by <a>Diagram</a>:</p>
173<ul>
174<li>"Model" - Animates all node positions when a new model is set.
175<li>"Layout" - Animates all changed node positions on a layout.
176</ul>
177
178
179<p>Invoked by <a>AnimationTrigger</a>s, if any are declared:</p>
180<ul>
181<li>"Trigger" - Animates the change of a defined <a>GraphObject</a> property.
182</ul>
183
184<p>
185The above quoted names are strings passed to <a>AnimationManager.canStart</a>
186This method can be overridden to return <code>false</code> if you wish to stop specific automatic animations.
187</p>
188
189<h3 id="DefaultAnimations">Default Initial Animation</h3>
190
191<p>
192 As of GoJS 2.1, the default initial animation fades the diagram upwards into view. Prior versions animated Part locations separately.
193 To control the initial animation behavior, there now exists <a>AnimationManager.initialAnimationStyle</a>, which is set to <a>AnimationManager,Default</a>
194 by default, but can be set to <a>AnimationManager,AnimateLocations</a> to use the animation style from GoJS 2.0.
195 You can also set this property to <a>AnimationManager,None</a> and define your own initial animation using the <code>"InitialAnimationStarting"</code> <a>DiagramEvent</a>.
196</p>
197
198<p>
199 Here is an example with buttons which set <a>AnimationManager.initialAnimationStyle</a> to the three different values, then reload the Diagram.
200 A fourth button illustrates how one might use the <code>"InitialAnimationStarting"</code> <a>DiagramEvent</a> to make a custom "zoom in" animation.
201</p>
202
203
204<pre class="lang-js" id="animationStyles"><code>
205 diagram.nodeTemplate =
206 $(go.Node, "Auto",
207 $(go.Shape, "RoundedRectangle", { strokeWidth: 0, fill: "lightblue" }),
208 $(go.TextBlock,
209 { margin: 8, font: "bold 14px sans-serif", stroke: '#333' },
210 new go.Binding("text", "key"))
211 );
212 diagram.model = new go.GraphLinksModel([{ key: 'Alpha' }, { key: 'Beta' }, { key: 'Delta' }, { key: 'Gamma' }]);
213
214 // only needed for this demonstration, this flag is used to stop
215 // the "InitialAnimationStarting" listener when other buttons are pressed
216 window.custom = false;
217
218 window.animateDefault = function() {
219 window.custom = false;
220 diagram.animationManager.initialAnimationStyle = go.AnimationManager.Default;
221 diagram.model = go.Model.fromJSON(diagram.model.toJSON());
222 }
223 window.animateLocations = function() {
224 window.custom = false;
225 diagram.animationManager.initialAnimationStyle = go.AnimationManager.AnimateLocations;
226 diagram.model = go.Model.fromJSON(diagram.model.toJSON());
227 }
228 window.animateNone = function() {
229 window.custom = false;
230 diagram.animationManager.initialAnimationStyle = go.AnimationManager.None;
231 diagram.model = go.Model.fromJSON(diagram.model.toJSON());
232 }
233 window.animateCustom = function() {
234 window.custom = true;
235 diagram.animationManager.initialAnimationStyle = go.AnimationManager.None;
236 // Customer listener zooms-in the Diagram on load:
237 diagram.addDiagramListener("InitialAnimationStarting", function(e) {
238 var animation = e.subject.defaultAnimation;
239 if (window.custom === false) {
240 // a different button was pressed, restore default values on the default animation:
241 animation.easing = go.Animation.EaseInOutQuad;
242 animation.duration = NaN;
243 return;
244 }
245 animation.easing = go.Animation.EaseOutExpo;
246 animation.duration = 1500;
247 animation.add(e.diagram, 'scale', 0.1, 1);
248 animation.add(e.diagram, 'opacity', 0, 1);
249 })
250 diagram.model = go.Model.fromJSON(diagram.model.toJSON());
251 }
252
253 </code></pre>
254 <script>goCode("animationStyles", 600, 200, null, true)</script>
255 <p>
256 <button id="Animate Colors" onclick="animateDefault()">animationStyle: Default</button>
257 <button id="Animate Colors" onclick="animateLocations()">animationStyle: AnimateLocations</button>
258 <button id="Animate Colors" onclick="animateNone()">animationStyle: None (does nothing!)</button>
259 <button id="Animate Colors" onclick="animateCustom()">animationStyle: None + Custom Animation</button>
260
261
262
263<h3 id="Limitations">Limitations of Default Animations</h3>
264
265<p>
266 The AnimationManager can be turned off by setting <a>AnimationManager.isEnabled</a> to <code>false</code>.
267 Specific default animations can be turned off or modified by overriding <a>AnimationManager.canStart</a>
268 and potentially returning <code>false</code>.
269</p>
270
271<p>
272 The default animation will be stopped if a new transaction begins during the animation.
273 The same is not true of other <a>Animation</a>s, which are not stopped by new transactions, and can continue indefinitely.
274</p>
275
276
277<h2 id="AnimatableProperties">Animatable Properties</h2>
278<p>
279 By default, <a>AnimationTriggers</a> and <a>Animation</a>s can animate these properties of GraphObjects:
280</p>
281<ul>
282 <li><code>position</code>
283 <li><code>location</code> (on Parts)
284 <li><code>scale</code>
285 <li><code>opacity</code>
286 <li><code>angle</code>
287 <li><code>desiredSize</code>
288 <li><code>width</code>
289 <li><code>height</code>
290 <li><code>background</code> (for solid string colors only)
291 <li><code>areaBackground</code> (for solid string colors only)
292 <li><code>fill</code> (on Shapes, for solid string colors only)
293 <li><code>strokeWidth</code> (on Shapes)
294 <li><code>strokeDashOffset</code> (on Shapes)
295 <li><code>stroke</code> (on Shapes, TextBlocks, for solid string colors only)
296</ul>
297
298<p>
299 Additionally <a>Animation</a>s (but not <a>AnimationTriggers</a>) can animate these properties of Diagram:
300</p>
301<ul>
302 <li><code>position</code>
303 <li><code>scale</code>
304 <li><code>opacity</code>
305</ul>
306
307<p>
308It is possible to animate other properties if they are defined by the programmer -- see the section "Custom Animation Effects" below.
309</p>
310
311<h2 id="AnimationTriggerClass">The AnimationTrigger Class</h2>
312
313<p class="box" style="background-color: lightgoldenrodyellow;">
314 <em>New in 2.1</em>
315</p>
316
317<p>
318 An <a>AnimationTrigger</a> is used to declare GraphObject properties to animate when their value has changed.
319 When a trigger is defined, changes to the target property will animate from the old value to the new value.
320 In templates, triggers are defined in a similar fashion to Bindings:
321</p>
322
323<pre class="lang-js"><code>
324// In this shape definition, two triggers are defined on a Shape.
325// These will cause all changes to Shape.stroke and Shape.fill to animate
326// from their old values to their new values.
327$(go.Shape, "Rectangle",
328 { strokeWidth: 12, stroke: 'black', fill: 'white' },
329 new go.AnimationTrigger('stroke'),
330 new go.AnimationTrigger('fill')
331)
332</code></pre>
333
334<p>
335Here is an example, with an HTML button that sets the Shape's <code>stroke</code> and <code>fill</code> to new random values:
336</p>
337
338<pre class="lang-js" id="animateTrigger1"><code>
339diagram.nodeTemplate =
340 $(go.Node,
341 $(go.Shape, "Rectangle",
342 { strokeWidth: 12, stroke: 'black', fill: 'white' },
343 new go.AnimationTrigger('stroke'),
344 new go.AnimationTrigger('fill')
345 )
346 );
347
348diagram.model = new go.GraphLinksModel([{ key: 'Alpha' }]); // One node
349
350// attach this Diagram to the window to use a button
351window.animateTrigger1 = function() {
352 diagram.commit(function(diag) {
353 var node = diag.nodes.first();
354 node.elt(0).stroke = go.Brush.randomColor();
355 node.elt(0).fill = go.Brush.randomColor();
356 });
357}
358
359</code></pre>
360<script>goCode("animateTrigger1", 600, 200, null, true)</script>
361<p><button id="Animate Colors" onclick="animateTrigger1()">Animate Colors</button>
362
363<p>
364 AnimationTriggers can invoke an animation immediately, starting a new animation with each property of each GraphObject that has been modified,
365 or they can (much more efficiently) be bundled together into the default
366 animation (<a>AnimationManager.defaultAnimation</a>) and begin at the end of the next transaction.
367 These behaviors can be set with <a>AnimationTrigger.startCondition</a> by the values
368 <a>AnimationTrigger,Immediate</a> and <a>AnimationTrigger,Bundled</a>, respectively.
369 The default value, <a>AnimationTrigger,Default</a>, attempts to infer which is best.
370 It will start immediately if there is no ongoing transaction or if <a>Diagram.skipsUndoManager</a> is true.
371</p>
372
373<p>
374 AnimationTriggers are only definable in templates, on GraphObjects, and cannot be used on RowColumnDefinitions or Diagrams.
375</p>
376
377<h2 id="AnimationClass">The Animation Class</h2>
378
379<p class="box" style="background-color: lightgoldenrodyellow">
380 <em>New in 2.1</em>
381</p>
382<p>
383 General animation of GraphObject and Diagram properties is possible by creating one or more instances of the <a>Animation</a> class.
384</p>
385
386<pre class="lang-js"><code>
387var animation = new go.Animation();
388// Animate the node's angle from its current value to a random value between 0 and 180 degrees
389animation.add(node, "angle", node.angle, Math.random() * 180);
390animation.duration = 1000; // Animate over 1 second, instead of the default 600 milliseconds
391animation.start(); // starts the animation immediately
392</code></pre>
393
394<p>
395 <a>Animation.add</a> is used to specify which objects should animate, which properties, and their starting and ending values:
396</p>
397
398<pre class="lang-js"><code>
399 animation.add(GraphObjectOrDiagram, "EffectName", StartingValue, EndingValue);
400</code></pre>
401
402<p>
403 Here's the above animation in an example, where each node is animated by an HTML button.
404 Note carefully that each node is added to the same animation. The same effect would be had with one animation per node,
405 but it is always more efficient to group the properties you are animating into a single animation, if possible
406 (for instance, it is possible if they are all going to start at the same time and have the same duration).
407</p>
408
409<pre id="animate1" class="lang-js"><code>
410// define a simple Node template
411diagram.nodeTemplate =
412 $(go.Node, "Spot",
413 { locationSpot: go.Spot.Center },
414 new go.Binding("angle"),
415 $(go.Shape, "Diamond", { strokeWidth: 0, width: 75, height: 75 },
416 new go.Binding("fill", "color")),
417 $(go.TextBlock,
418 { margin: 8, font: 'bold 12pt sans-serif' },
419 new go.Binding("text", "key"))
420 );
421
422diagram.model = new go.GraphLinksModel(
423 [
424 { key: "Alpha", color: "lightblue" },
425 { key: "Beta", color: "orange" },
426 { key: "Gamma", group: 'G1', color: "lightgreen" },
427 { key: "Delta", group: 'G1', color: "pink", angle: 45 }
428 ],
429 [
430 { from: "Alpha", to: "Beta" },
431 { from: "Gamma", to: "Delta" }
432 ]);
433
434window.animate1 = function() {
435 var animation = new go.Animation();
436 diagram.nodes.each(function(node) {
437 // Animate the node's angle from its current value to a random value between 0 and 150 degrees
438 animation.add(node, "angle", node.angle, Math.random() * 150);
439 });
440 animation.duration = 1000; // Animate over 1 second, instead of the default 600 milliseconds
441 animation.start(); // starts the animation immediately
442}
443</code></pre>
444<script>goCode("animate1", 600, 250, null, true)</script>
445<p><button id="Animate Nodes" onclick="animate1()">Animate Node Angles</button>
446
447<p>
448 Animating the Diagram is possible by passing it as the object to be animated:
449</p>
450<pre class="lang-js"><code>
451 animation.add(myDiagram, "position", myDiagram.position, myDiagram.position.copy().offset(200, 15));
452 ...
453 animation.add(myDiagram, "scale", myDiagram.scale, 0.2);
454</code></pre>
455
456<p>
457 Animations can also be reversed, as is common with animations that are intended to be cosmetic in nature, by setting <a>Animation.reversible</a> to true.
458 This doubles the effective duration of the Animation.
459</p>
460<p>
461 Below are several example Animations, all with <a>Animation.reversible</a> set to true. The first animates Nodes, the other three animate Diagram position and scale.
462</p>
463
464<pre class="lang-js" id="animate2"><code>
465 // define a simple Node template
466 diagram.nodeTemplate =
467 $(go.Node, "Spot",
468 { locationSpot: go.Spot.Center },
469 new go.Binding("angle"),
470 $(go.Shape, "Diamond", { strokeWidth: 0, width: 75, height: 75 },
471 new go.Binding("fill", "color")),
472 $(go.TextBlock,
473 { margin: 8, font: 'bold 12pt sans-serif' },
474 new go.Binding("text", "key"))
475 );
476
477 diagram.model = new go.GraphLinksModel(
478 [
479 { key: "Alpha", color: "lightblue" },
480 { key: "Beta", color: "orange" },
481 { key: "Gamma", group: 'G1', color: "lightgreen" },
482 { key: "Delta", group: 'G1', color: "pink" }
483 ],
484 [
485 { from: "Alpha", to: "Beta" },
486 { from: "Gamma", to: "Delta" }
487 ]);
488
489 function protectedAnimation(f) { // return a button event handler to start an animation
490 return function() {
491 // Stop any currently running animations
492 diagram.animationManager.stopAnimation(true);
493
494 var animation = new go.Animation();
495 animation.reversible = true; // reverse the animation at the end, doubling its total time
496 f(animation); // initialize the Animation
497 animation.start(); // start the animation immediately
498 };
499 }
500
501 window.animateAngleReverse =
502 protectedAnimation(function(animation) {
503 diagram.nodes.each(function(node) {
504 // Animate the node's angle from its current value a random value between 0 and 90
505 animation.add(node, "angle", node.angle, Math.random() * 90);
506 });
507 });
508
509 window.animateDiagramPosition =
510 protectedAnimation(function(animation) {
511 // shift the diagram contents towards the right and then back
512 animation.add(diagram, "position", diagram.position, diagram.position.copy().offset(200, 15));
513 animation.duration = 700;
514 });
515
516 window.animateZoomOut =
517 protectedAnimation(function(animation) {
518 animation.add(diagram, "scale", diagram.scale, 0.2);
519 });
520
521 window.animateZoomIn =
522 protectedAnimation(function(animation) {
523 animation.add(diagram, "scale", diagram.scale, 4);
524 });
525 </code></pre>
526 <script>goCode("animate2", 600, 250, null, true)</script>
527 <p>
528 <button id="AnimateAngleReverse" onclick="animateAngleReverse()">Animate Angles (reverse)</button>
529 <button id="AnimateDiagramPosition" onclick="animateDiagramPosition()">Animate Diagram Position (reverse)</button>
530 <button id="AnimateZoomOut" onclick="animateZoomOut()">Zoom Out (reverse)</button>
531 <button id="AnimateZoomIn" onclick="animateZoomIn()">Zoom In (reverse)</button>
532 </p>
533 <p>
534 Without the call to <a>AnimationManager.stopAnimation</a> to protect against rapid button clicks,
535 you would notice that if you clicked Zoom Out, and then during the animation clicked the same button again,
536 the Diagram's scale would not return to its initial value of 1.0.
537 This is because the Animation animates from the <em>current</em> Diagram scale value, to its final value, and back again,
538 but the current value is also what's being changed due to the ongoing animation.
539 </p>
540
541 <h3 id="CustomAnimationEffects">Custom Animation Effects</h3>
542
543 <p>
544 It is sometimes helpful to add custom ways to modify one or more properties during an animation.
545 You can register new animatable effects with <a>AnimationManager,defineAnimationEffect</a>.
546 The name passed is an arbitrary string, but often reflects a property of a GraphObject class.
547 The body of the function passed determines what property or properties are animated.
548 </p>
549 <p>
550
551 </p>
552 <p>
553 Here is an example, creating an <code>"fraction"</code> Animation effect to animate the value of <a>GraphObject.segmentFraction</a>,
554 which will give the appearance of a Link label moving along its path.
555 </p>
556<pre class="lang-js"><code>
557// This presumes the object to be animated is a label within a Link
558go.AnimationManager.defineAnimationEffect('fraction',
559function(obj, startValue, endValue, easing, currentTime, duration, animation) {
560 obj.segmentFraction = easing(currentTime, startValue, endValue - startValue, duration);
561});
562</code></pre>
563
564<p>
565 After defining this, we can use it as a property name in an Animation.
566 The following example sets up an indefinite (<a>Animation.runCount</a> = <code>Infinity</code>) and reversible
567 animation, where each link is assigned a random duration to cycle the fill color and segmentFraction of its label.
568 This produces labels that appear to move along their path while pulsating colors. The setting of <a>Animation.reversible</a>
569 causes them to go backwards once finished, to start from their beginning again.
570</p>
571<pre class="lang-js"><code>
572 function animateColorAndFraction() {
573 // create one Animation for each link, so that they have independent durations
574 myDiagram.links.each(function(node) {
575 var animation = new go.Animation()
576 animation.add(node.elt(1), "fill", node.elt(0).fill, go.Brush.randomColor());
577 animation.add(node.elt(1), "fraction", 0, 1);
578 animation.duration = 1000 + (Math.random()*2000);
579 animation.reversible = true; // Re-run backwards
580 animation.runCount = Infinity; // Animate forever
581 animation.start();
582 });
583 }
584</code></pre>
585
586<pre id="animate3" style="display: none;"><code>
587 diagram.nodeTemplate =
588 $(go.Node, "Auto",
589 $(go.Shape, "RoundedRectangle", { strokeWidth: 0 },
590 new go.Binding("fill", "color")),
591 $(go.TextBlock,
592 { margin: 8 },
593 new go.Binding("text", "key"))
594 );
595
596 diagram.linkTemplate =
597 $(go.Link,
598 $(go.Shape, { strokeWidth: 2 }),
599 // The label
600 $(go.Shape, "Circle", { segmentIndex: 0, width: 15, height: 15, fill: 'red', strokeWidth: 2 })
601 );
602
603 diagram.model = new go.GraphLinksModel(
604 [
605 { key: "Alpha", color: "lightblue" },
606 { key: "Gamma", color: "lightgreen" },
607 { key: "Delta", color: "pink" }
608 ],
609 [
610 { from: "Alpha", to: "Gamma" },
611 { from: "Gamma", to: "Delta" },
612 { from: "Delta", to: "Alpha" }
613 ]);
614
615
616 // This presumes the object to be animated is a label within a Link
617 go.AnimationManager.defineAnimationEffect('fraction',
618 function(obj, startValue, endValue, easing, currentTime, duration, animation) {
619 obj.segmentFraction = easing(currentTime, startValue, endValue - startValue, duration);
620 });
621
622
623 window.animateColorAndFraction = function() {
624 // create one Animation for each link, so that they have independent durations
625 diagram.links.each(function(node) {
626 var animation = new go.Animation()
627 animation.add(node.elt(1), "fill", node.elt(0).fill, go.Brush.randomColor());
628 animation.add(node.elt(1), "fraction", 0, 1);
629 animation.duration = 1000 + (Math.random()*2000);
630 animation.reversible = true; // Re-run backwards
631 animation.runCount = Infinity; // Animate forever
632 animation.start();
633 });
634 }
635 </code></pre>
636 <script>goCode("animate3", 600, 200, null, true)</script>
637 <p><button id="animateColorAndFraction" onclick="animateColorAndFraction()">Animate Color and Segment Fraction</button>
638
639 <p>Since <a>Animation.runCount</a> was set to <code>Infinity</code>, this Animation wil run indefinitely.</p>
640
641 <h3 id="AnimatingDeletion">Animating Deletion</h3>
642
643 <p>
644 Parts to be deleted can be animated, but since they will no longer exist in the Diagram after removal,
645 a copy must be added to the Animation so that there is an object to animate.
646 This can be done with <a>Animation.addTemporaryPart</a>.
647 The part can then have its deletion animated using <a>Animation.add</a>.
648 This temporary part will be the object that animates,
649 and will automatically appear when animation begins and be removed when animaton completes.
650 It is typical for deletion animations to shrink the mock Part, move it off-screen, reduce its opacity to zero,
651 or otherwise show it disappearing in some way.
652 </p>
653 <p>
654 In this example, each Part being deleted will be scaled to an imperceptible size (by animating scale to 0.01)
655 and spun around (by animating angle), to give the appearance of swirling away. There are other example
656 deletion (and creation) effects in the <a href="../samples/customAnimations.html">Custom Animations extension sample</a>.
657 </p>
658 <pre class="lang-js"><code>
659myDiagram.addDiagramListener('SelectionDeleting', function(e) {
660 // the DiagramEvent.subject is the collection of Parts about to be deleted
661 e.subject.each(function(part) {
662 if (!(part instanceof go.Node)) return; // only animate Nodes
663 var animation = new go.Animation();
664 var deletePart = part.copy();
665 animation.add(deletePart, "scale", deletePart.scale, 0.01);
666 animation.add(deletePart, "angle", deletePart.angle, 360);
667 animation.addTemporaryPart(deletePart, myDiagram);
668 animation.start();
669 });
670});
671</code></pre>
672
673
674<pre id="animate4" style="display: none;">
675 // define a simple Node template
676 diagram.nodeTemplate =
677 $(go.Node, "Spot",
678 { locationSpot: go.Spot.Center },
679 new go.Binding("angle"),
680 $(go.Shape, "Ellipse",
681 {
682 fill: "hsl(" + ((Math.random()*360)|0) + ", 100%, 80%)",
683 strokeWidth: 4, strokeDashArray: [8, 8],
684 width: 55, height: 55
685 }),
686 $(go.TextBlock,
687 new go.Binding("text", "key"))
688 );
689
690 diagram.model = new go.GraphLinksModel(
691 [
692 { key: "Alpha" },
693 { key: "Beta" },
694 { key: "Gamma" },
695 { key: "Delta" }
696 ],
697 [ ]);
698
699 diagram.addDiagramListener('SelectionDeleting', function(e) {
700 // the DiagramEvent.subject is the collection of Parts about to be deleted
701 e.subject.each(function(part) {
702 if (!(part instanceof go.Node)) return; // only animate Nodes
703 var animation = new go.Animation();
704 var deletePart = part.copy();
705 animation.add(deletePart, "scale", deletePart.scale, 0.01);
706 animation.add(deletePart, "angle", deletePart.angle, 360);
707 animation.addTemporaryPart(deletePart, diagram);
708 animation.start();
709 });
710 });
711
712 window.deleteNode = function() {
713 if (diagram.selection.count === 0) diagram.select(diagram.nodes.first());
714 diagram.commandHandler.deleteSelection();
715 }
716 </code></pre>
717 <script>goCode("animate4", 600, 200, null, true)</script>
718 <p><button onclick="deleteNode()">Delete a Node</button>
719
720
721 <h3 id="AnimationExamples">Animation Examples</h3>
722
723 <p>
724 To see more examples of custom animations, visit the <a href="../samples/customAnimations.html">Custom Animations extension sample</a>.
725 It demonstrates a number of Node creation/deletion animations, linking animations, and more.
726 There are also several samples which contain animation:
727 </p>
728
729 <ul>
730 <li><a href="../samples/animatedFocus.html" target="_blank">Animated Focus</a> - Scroll to center a Node in the viewport, while zooming a copy of that node for attention.</li>
731 <li><a href="../samples/treeLoadAnimation.html" target="_blank">Tree Load Animation</a> - Recursive animation upon model load.</li>
732 <li><a href="../samples/dataVisualization.html" target="_blank">Data Visualization</a> - Nodes now move using an <a>AnimationTrigger</a>.</li>
733 <li><a href="../samples/kittenMonitor.html" target="_blank">Kitten Monitor</a> - Kittens now move using an <a>AnimationTrigger</a>.</li>
734 <li><a href="../samples/processFlow.html" target="_blank">Process Flow</a> - Custom animation defined to animate the Link Shape's strokeDashArray.</li>
735 <li><a href="../samples/belts.html" target="_blank">Belts and Rollers</a> - Apparent movement of the belts by animating the strokeDashArray.</li>
736 <li><a href="../samples/shopFloorMonitor.html" target="_blank">Shop Floor Monitor</a> - Link color changes now use an <a>AnimationTrigger</a>.</li>
737 <li><a href="../samples/flowchart.html" target="_blank">Flowchart</a> - In the Palette only, initial animation is disabled in favor of a custom fade-in animation.</li>
738 <li><a href="../samples/stateChart.html" target="_blank">State Chart</a> - Initial animation is disabled in favor of a custom zoom fade-in animation.</li>
739 </ul>
740
741 </div>
742 </div>
743
744 <div class="bg-nwoods-primary">
745 <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
746 <p id="version" class="leading-none mb-2 my-4">GoJS</p>
747 </section>
748 </div><footer class="bg-nwoods-primary text-white">
749 <div class="container max-w-screen-lg mx-auto px-8">
750 <div class="w-full py-6">
751
752 <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
753 <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
754 <li class="list-none row-span-2">
755 <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
756 <ul class="list-none space-y-4 md:space-y-1 px-0">
757 <li>
758 <a href="../samples/index.html">Samples</a>
759 </li>
760 <li>
761 <a href="../learn/index.html">Learn</a>
762 </li>
763 <li>
764 <a href="../intro/index.html">Intro</a>
765 </li>
766 <li>
767 <a href="../api/index.html">API</a>
768 </li>
769 <li>
770 <a href="../changelog.html">Changelog</a>
771 </li>
772 <li>
773 <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
774 </li>
775 </ul>
776 </li>
777 <li class="list-none row-span-2">
778 <h2 class="text-base font-semibold tracking-wide">Support</h2>
779 <ul class="list-none space-y-4 md:space-y-1 px-0">
780 <li>
781 <a href="https://www.nwoods.com/contact.html"
782 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
783 </li>
784 <li>
785 <a href="https://forum.nwoods.com/c/gojs">Forum</a>
786 </li>
787 <li>
788 <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
789 </li>
790 <li>
791 <a href="https://www.nwoods.com/sales/index.html"
792 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
793 </li>
794 <li>
795 <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
796 </li>
797 </ul>
798 </li>
799 <li class="list-none row-span-2">
800 <h2 class="text-base font-semibold tracking-wide">Company</h2>
801 <ul class="list-none space-y-4 md:space-y-1 px-0">
802 <li>
803 <a href="https://www.nwoods.com">Northwoods</a>
804 </li>
805 <li>
806 <a href="https://www.nwoods.com/about.html">About Us</a>
807 </li>
808 <li>
809 <a href="https://www.nwoods.com/contact.html">Contact Us</a>
810 </li>
811 <li>
812 <a href="https://twitter.com/northwoodsgo">Twitter</a>
813 </li>
814
815 </ul>
816 </li>
817 </ul>
818
819
820 <p class="text-sm text-gray-100 md:mb-6">
821 Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
822 </p>
823 </div>
824 </div>
825</footer> </body>
826
827<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
828<script>
829 window.dataLayer = window.dataLayer || [];
830 function gtag(){dataLayer.push(arguments);}
831 gtag('js', new Date()); gtag('config', 'UA-1506307-5');
832 var getOutboundLink = function(url, label) {
833 gtag('event', 'click', {
834 'event_category': 'outbound',
835 'event_label': label,
836 'transport_type': 'beacon'
837 });
838 }
839
840 // topnav
841 var topButton = document.getElementById("topnavButton");
842 var topnavList = document.getElementById("topnavList");
843 topButton.addEventListener("click", function() {
844 this.classList.toggle("active");
845 topnavList.classList.toggle("hidden");
846 document.getElementById("topnavOpen").classList.toggle("hidden");
847 document.getElementById("topnavClosed").classList.toggle("hidden");
848 });
849</script>
850 <script src="../assets/js/prism.js"></script>
851 <script src="../release/go.js"></script>
852 <script src="../assets/js/goDoc.js"></script>
853 <script>
854 document.addEventListener("DOMContentLoaded", function() {
855 if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
856 if (window.goDoc) window.goDoc();
857 var d = window.diagrams;
858 for (var i = 0; i < d.length; i++) {
859 var dargs = d[i];
860 goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
861 }
862 if (window.extra) window.extra();
863 });
864 </script>
865</html>