|
| 1 | +--- |
| 2 | +id: javafx.animation |
| 3 | +title: Introduction to JavaFX animations |
| 4 | +slug: learn/javafx-animations |
| 5 | +type: tutorial |
| 6 | +group: rich-client-apps |
| 7 | +category: javafx |
| 8 | +category_order: 2 |
| 9 | +layout: learn/tutorial.html |
| 10 | +subheader_select: tutorials |
| 11 | +main_css_id: learn |
| 12 | +description: "Learn to create advanced JavaFX animations" |
| 13 | +last_update: 2024-05-17 |
| 14 | +--- |
| 15 | + |
| 16 | +The [javafx.animation](javafxdoc:AnimationPackageSummary) package in JavaFX offers a simple framework for creating animations and transitions in a JavaFX application. |
| 17 | +It operates on the principle of [WritableValue\<T\>](javafxdoc:WritableValue) which are used across JavaFX. |
| 18 | +It additionally provides a variety of built-in transitions for common effects, support for parallel and sequential transitions, and the ability to handle events upon animation completion. |
| 19 | +I will go through all types of animations, starting with `Animation` and its subclasses `Transition` and `Timeline`, before representing a lower level animation with `AnimationTimer`. |
| 20 | +While `Transition` provides a simpler and more user-friendly way to create animations, `Timeline` offers greater flexibility and is suitable for more complex animations. |
| 21 | +In contrast, `AnimationTimer` is designed for frame-by-frame updates and does not take use of `WritableValue<T>`. |
| 22 | + |
| 23 | +## Animation |
| 24 | + |
| 25 | +The [Animation](javafxdoc:Animation) abstract class provides the core functionality for `Transition` and `Timeline` animations. |
| 26 | + |
| 27 | +An `Animation` consists of multiple properties: |
| 28 | +- The `targetFramerate` is the maximum framerate (frames per s) at which this `Animation` will run. |
| 29 | +- The `currentTime` is the current point in time as a `Duration` of the `Animation`. |
| 30 | +- The `rate` defines the direction and speed at which the `Animation` is expected to be played. It supports both positive and negative numbers. |
| 31 | +- The `cycleCount` defines the number of cycles of this `Animation`. It can't be changed while running and must be positive. |
| 32 | +- The `cycleDuration` is the `Duration` of one cycle of this `Animation`. It is the time it takes to play from start to end of the `Animation` **at the default rate of 1.0**. |
| 33 | +- The `totalDuration` indicates the total duration of this `Animation`, including repeats. It is the result of `cycleDuration * cycleCount` or possibly `Duration.INDEFINITE`. |
| 34 | +- The `delay` is the `Duration` that delays the `Animation` when starting. |
| 35 | +- The `autoReverse` property specifies whether the `Animation` will play in reverse direction on alternating cycles. |
| 36 | +- The `onFinished` event handler is used to define additional behavior when the `Animation` finished. |
| 37 | +- The `status` represents the current state of the `Animation`, possible states are `PAUSED`, `RUNNING` and `STOPPED`. |
| 38 | + |
| 39 | +Additionally, it provides several useful methods, like `play()`, `playFrom(String cuePoint)`, `pause()`, `stop()` and more to control the animations flow. |
| 40 | +A quick look into the JavaDocs provides a great overview of its functionalities. |
| 41 | + |
| 42 | +## Transition |
| 43 | +The [Transition](javafxdoc:Transition) abstract class serves as the foundational class for all transitions, presenting a common form of `Animation`. |
| 44 | +JavaFX provides a variety of built-in transitions for common [Node](javafxdoc:Node) and [Shape](javafxdoc:Shape) properties. |
| 45 | + |
| 46 | +**Note:** By default, all transitions, excluding `ParallelTransition` and `SequentialTransition`, utilize the `Interpolator#EASE_BOTH`. |
| 47 | + |
| 48 | +### Fade Transition |
| 49 | +The [FadeTransition](javafxdoc:FadeTransition) creates a fade effect over a `duration`. |
| 50 | +This is done by updating the `opacity` property of the `Node` at regular intervals. |
| 51 | + |
| 52 | + |
| 53 | +```java |
| 54 | +Circle circle = new Circle(150, 150, 20, Color.GREEN); |
| 55 | + |
| 56 | +FadeTransition transition = new FadeTransition(Duration.seconds(5), circle); |
| 57 | +transition.setFromValue(1.0); |
| 58 | +transition.setToValue(0); |
| 59 | +transition.setInterpolator(Interpolator.LINEAR); |
| 60 | + |
| 61 | +transition.play(); |
| 62 | +``` |
| 63 | + |
| 64 | +### Fill Transition |
| 65 | +The [FillTransition](javafxdoc:FillTransition) creates an animation, that changes the filling of a shape over a `duration`. |
| 66 | +This is done by updating the `fill` property of the `Shape` at regular intervals. |
| 67 | + |
| 68 | + |
| 69 | +```java |
| 70 | +Circle circle = new Circle(150, 150, 20, Color.GREEN); |
| 71 | + |
| 72 | +FillTransition transition = new FillTransition(Duration.seconds(5), circle); |
| 73 | +transition.setFromValue(Color.GREEN); |
| 74 | +transition.setToValue(Color.BLACK); |
| 75 | +transition.setInterpolator(Interpolator.LINEAR); |
| 76 | + |
| 77 | +transition.play(); |
| 78 | +``` |
| 79 | + |
| 80 | +### Path Transition |
| 81 | +The [PathTransition](javafxdoc:PathTransition) creates a path animation that spans its `duration`. |
| 82 | +The translation along the path is done by updating the `translateX` and `translateY` properties of the `Node`, and the `rotate` variable will get updated if `orientation` is set to `OrientationType.ORTHOGONAL_TO_TANGENT`, at regular interval. |
| 83 | + |
| 84 | + |
| 85 | +```java |
| 86 | +Circle circle = new Circle(50, 50, 10, Color.GREEN); |
| 87 | + |
| 88 | +Path path = new Path(); |
| 89 | +path.getElements().add(new MoveTo(50, 50)); // starting point |
| 90 | +path.getElements().add(new LineTo(250, 250)); |
| 91 | + |
| 92 | +PathTransition transition = new PathTransition(Duration.seconds(5), path, circle); |
| 93 | +transition.setInterpolator(Interpolator.LINEAR); |
| 94 | + |
| 95 | +transition.play(); |
| 96 | +``` |
| 97 | + |
| 98 | +### Rotate Transition |
| 99 | +The [RotateTransition](javafxdoc:RotateTransition) creates a rotation animation that spans its `duration`. |
| 100 | +This is done by updating the `rotate` property of the `Node` at regular interval. The angle value is specified in degrees. |
| 101 | + |
| 102 | + |
| 103 | +```java |
| 104 | +Rectangle rectangle = new Rectangle(125, 125, 50, 50); |
| 105 | +rectangle.setFill(Color.GREEN); |
| 106 | + |
| 107 | + |
| 108 | +RotateTransition transition = new RotateTransition(Duration.seconds(5), rectangle); |
| 109 | +transition.setFromAngle(0); |
| 110 | +transition.setToAngle(360); |
| 111 | +transition.setInterpolator(Interpolator.LINEAR); |
| 112 | + |
| 113 | +transition.play(); |
| 114 | +``` |
| 115 | + |
| 116 | +### Scale Transition |
| 117 | +The [ScaleTransition](javafxdoc:ScaleTransition) creates a scale animation over a `duration`. |
| 118 | +This is done by updating the `scaleX`, `scaleY` and `scaleZ` properties of the `Node` at regular interval. |
| 119 | + |
| 120 | + |
| 121 | +```java |
| 122 | +Circle circle = new Circle(150, 150, 50, Color.GREEN); |
| 123 | + |
| 124 | +ScaleTransition transition = new ScaleTransition(Duration.seconds(5), circle); |
| 125 | +transition.setToX(0.1); |
| 126 | +transition.setToY(0.1); |
| 127 | +transition.setInterpolator(Interpolator.LINEAR); |
| 128 | + |
| 129 | +transition.play(); |
| 130 | +``` |
| 131 | + |
| 132 | +### Stroke Transition |
| 133 | +The [StrokeTransition](javafxdoc:StrokeTransition) creates an animation, that changes the stroke color of a shape over a `duration`. |
| 134 | +This is done by updating the `stroke` property of the `Shape` at regular intervals. |
| 135 | + |
| 136 | + |
| 137 | +```java |
| 138 | +Circle circle = new Circle(150, 150, 50, Color.GREEN); |
| 139 | +circle.setStrokeWidth(5); |
| 140 | + |
| 141 | +StrokeTransition transition = new StrokeTransition(Duration.seconds(5), circle); |
| 142 | +transition.setFromValue(Color.GREEN); |
| 143 | +transition.setToValue(Color.BLACK); |
| 144 | +transition.setInterpolator(Interpolator.LINEAR); |
| 145 | + |
| 146 | +transition.play(); |
| 147 | +``` |
| 148 | + |
| 149 | +### Translate Transition |
| 150 | +The [TranslateTransition](javafxdoc:TranslateTransition) creates a move/translate animation that spans its `duration`. |
| 151 | +This is done by updating the `translateX`, `translateY` and `translateZ` properties of the `Node` at regular interval. |
| 152 | + |
| 153 | + |
| 154 | +```java |
| 155 | +Circle circle = new Circle(50, 50, 10, Color.GREEN); |
| 156 | + |
| 157 | +TranslateTransition transition = new TranslateTransition(Duration.seconds(5), circle); |
| 158 | +transition.setToX(200); |
| 159 | +transition.setToY(200); |
| 160 | +transition.setInterpolator(Interpolator.LINEAR); |
| 161 | + |
| 162 | +transition.play(); |
| 163 | +``` |
| 164 | + |
| 165 | +### Pause Transition |
| 166 | +The [PauseTransition](javafxdoc:PauseTransition) executes an `Animation.onFinished` at the end of its `duration`. |
| 167 | + |
| 168 | +### Parallel Transition |
| 169 | +The [ParallelTransition](javafxdoc:ParallelTransition) plays a list of animations in parallel. |
| 170 | + |
| 171 | +### Sequential Transition |
| 172 | +The [SequentialTransition](javafxdoc:SequentialTransition) plays a list of animations in sequential order. |
| 173 | +It is not recommended to contain an `Animation`, which is not the last one, with `Duration.INDEFINITE` as this will block all later animations in the sequence. |
| 174 | + |
| 175 | +## Timeline |
| 176 | +A [Timeline](javafxdoc:Timeline) is used to define a free form `Animation` of any `WritableValue<T>`. It is helpful if none of the built-in transitions operate on the required properties. |
| 177 | + |
| 178 | +It consists of a sequential series of `KeyFrame`. |
| 179 | +Each `KeyFrame` encapsulates a moment in time (**Cue Point**), and collectively specify how target properties evolve over the entire duration. |
| 180 | + |
| 181 | +> **Warning:** A running Timeline is being referenced from the FX runtime. Infinite Timeline might result in a memory leak if not stopped properly. All the objects with animated properties would not be garbage collected. |
| 182 | +
|
| 183 | +### KeyFrame |
| 184 | +A [KeyFrame](javafxdoc:KeyFrame) represents a specific moment in an animation sequence (**Cue Point**) and comprises a collection of `KeyValue` instances that change from start to the given `Duration`. |
| 185 | + |
| 186 | +A KeyFrame can have a name which then can be used to identify this `KeyFrame` in an animation, for example for starting from this specific `KeyFrame` using `playFrom(String cuePoint)`. |
| 187 | +It is also possible to provide an `onFinished` implementation, which will be invoked when hitting this cue point. |
| 188 | + |
| 189 | +### KeyValue |
| 190 | +A [KeyValue](javafxdoc:KeyValue) establishes a mapping between a `WritableValue<T>` and a target value of type `T`. This is used to define the change of a value. |
| 191 | +An `Interpolator` can be additionally defined to set the rate of change for this value. The `KeyValue` class is immutable. |
| 192 | + |
| 193 | +### Example |
| 194 | +This example of `Timeline` creates a `Circle` which moves 200px in x direction over the duration of 5 seconds: |
| 195 | + |
| 196 | + |
| 197 | +```java |
| 198 | +Circle circle = new Circle(50, 150, 10, Color.GREEN); |
| 199 | + |
| 200 | +KeyValue x = new KeyValue(circle.translateXProperty(), 200); |
| 201 | +KeyFrame frame = new KeyFrame(Duration.seconds(5), x); |
| 202 | +Timeline timeline = new Timeline(frame); |
| 203 | + |
| 204 | +timeline.play(); |
| 205 | +``` |
| 206 | + |
| 207 | +## Interpolator |
| 208 | +The [Interpolator](javafxdoc:Interpolator) abstract class defines the rate of change at which values change over time, influencing the smoothness of animations. |
| 209 | + |
| 210 | +It provides several built-in implementations: |
| 211 | +- [Interpolator.DISCRETE](javafxdoc:Interpolator.DISCRETE): The `DISCRETE` interpolator creates a **sudden** transition between values without any intermediate steps. |
| 212 | +- [Interpolator.LINEAR](javafxdoc:Interpolator.LINEAR): The `LINEAR` interpolator produces a **constant** rate of change between values over time. |
| 213 | +- [Interpolator.EASE_IN](javafxdoc:Interpolator.EASE_IN): The `EASE_IN` interpolator starts the animation slowly and accelerates as it progresses. |
| 214 | +- [Interpolator.EASE_OUT](javafxdoc:Interpolator.EASE_OUT): The `EASE_OUT` interpolator starts quickly and slows down as it progresses. |
| 215 | +- [Interpolator.EASE_BOTH](javafxdoc:Interpolator.EASE_BOTH): The `EASE_BOTH` interpolator starts slowly, accelerates in the middle and slows down towards the end. It combines the characteristics of `EASE_IN` and `EASE_OUT`. |
| 216 | + |
| 217 | +Additionally, there are two static factory methods for [SPLINE](javafxdoc:Interpolator.SPLINE) and [TANGENT](javafxdoc:Interpolator.TANGENT) interpolation. |
| 218 | + |
| 219 | +[//]: # (ToDo: sync gifs) |
| 220 | +Here is a visualization of the Interpolator using the example from [Timeline](#example): |
| 221 | +### Discrete |
| 222 | + |
| 223 | +### Linear |
| 224 | + |
| 225 | +### Ease In |
| 226 | + |
| 227 | +### Ease Out |
| 228 | + |
| 229 | +### Ease Both |
| 230 | + |
| 231 | + |
| 232 | +## AnimationTimer |
| 233 | + |
| 234 | +The [AnimationTimer](javafxdoc:AnimationTimer) abstract class provides the lowest level option to create an animation. |
| 235 | +The `handle(long now)` method gets called in each frame while it is active. The timestamp `long now` is the nanoseconds time of the current frame and will be the same for all `AnimationTimer` called during that frame. |
| 236 | +Additionally, the `AnimationTimer` adds the `start()` and `stop()` to handle the lifetime of the animation. |
| 237 | + |
| 238 | +**Note:** The handle method will be called on the **JavaFX Application Thread** and thus shouldn't do heavy computations. |
| 239 | + |
| 240 | + |
| 241 | +## Conclusion |
| 242 | +The `javafx.animation` package offers a simple framework for creating dynamic animations within JavaFX applications. |
| 243 | +From the foundational `AnimationTimer` and `Animation` classes to the more specialized `Transition` and `Timeline` classes, |
| 244 | +each component provides unique capabilities for creating animations. Additionally, you are provided with various |
| 245 | +common `Interpolator` implementations. |
0 commit comments