What animation is in JavaFX
About classes in JavaFX that are used in performing animation in JavaFX
How to perform a timeline animation and how to set up cue points on a timeline animation
How to control animation such as playing, reversing, pausing, and stopping
How to perform animation using transitions
About different types of interpolators and their roles in animation
What Is Animation?
In the real world, animation implies some kind of motion, which is generated by displaying images in quick succession. For example, when you watch a movie, you are watching images, which change so quickly that you get an illusion of motion.
In JavaFX, animation is defined as changing the property of a node over time. If the property that changes determines the location of the node, the animation in JavaFX will produce an illusion of motion as found in movies. Not all animations have to involve motion; for example, changing the fill property of a shape over time is an animation in JavaFX that does not involve motion.
Timeline
Key frame
Key value
Interpolator
Animation is performed over a period of time. A timeline denotes the progression of time during animation with an associated key frame at a given instant. A key frame represents the state of the node being animated at a specific instant on the timeline. A key frame has associated key values. A key value represents the value of a property of the node along with an interpolator to be used.
The developer provides timelines, key frames, and key values. In this example, there are five key frames. If JavaFX shows only five key frames at the five respective instants, the animation will look jerky. To provide a smooth animation, JavaFX needs to interpolate the position of the circle at any instant on the timeline. That is, JavaFX needs to create intermediate key frames between two consecutive provided key frames. JavaFX does this with the help of an interpolator. By default, it uses a linear interpolator , which changes the property being animated linearly with time. That is, if the time on the timeline passes x%, the value of the property will be x% between the initial and final target values. Circles with the dashed outline are created by JavaFX using an interpolator.
Understanding Animation Classes
The abstract Animation class represents an Animation. It contains common properties and methods used by all types of animation.
Timeline animations
Transitions
In a timeline animation, you create a timeline and add key frames to it. JavaFX creates the intermediate key frames using an interpolator. An instance of the Timeline class represents a timeline animation. This type of animation requires a little more code, but it gives you more control.
Several types of animations are commonly performed (moving a node along a path, changing the opacity of a node over time, etc.). These types of animations are known as transitions. They are performed using an internal timeline. An instance of the Transition class represents a transition animation. Several subclasses of the Transition class exist to support specific types of transitions. For example, the FadeTransition class implements a fading effect animation by changing the opacity of a node over time. You create an instance of the Transition class (typically, an instance of one of its subclasses) and specify the initial and final values for the property to be animated and the duration for the animation. JavaFX takes care of creating the timeline and performing the animation. This type of animation is easier to use.
Sometimes, you may want to perform multiple transitions sequentially or simultaneously. The SequentialTransition and ParallelTransition classes let you perform a set of transitions sequentially and simultaneously, respectively.
Understanding Utility Classes
Before discussing the details of JavaFX animation, I will discuss a few utility classes that are used in implementing animations. The following sections will discuss those classes.
Understanding the Duration Class
The Duration class is in the javafx.util package. It represents a duration of time in milliseconds, seconds, minutes, and hours. It is an immutable class. A Duration represents the amount of time for each cycle of an animation. A Duration can represent a positive or negative duration.
Using the constructor
Using factory methods
Using the valueOf() method from a duration in String format
You can also represent a duration of an unknown amount of time and an indefinite time using the UNKNOWN and INDEFINITE constants of the Duration class, respectively. You can use the isIndefinite() and isUnknown() methods to check if a duration represents an indefinite or unknown amount of time. The class declares two more constants, ONE and ZERO, that represent durations of one millisecond and zero (no time), respectively.
Using the Duration Class
Understanding the KeyValue Class
A target
An end value for the target
An interpolator
The target is a WritableValue, which qualifies all JavaFX properties to be a target. The end value is the value for the target at the end of the interval. The interpolator is used to compute the intermediate key frames.
KeyValue(WritableValue<T> target, T endValue)
KeyValue(WritableValue<T> target, T endValue, Interpolator interpolator)
The Interpolator.LINEAR is used as the default interpolator that interpolates the animated property linearly with time. I will discuss different types of interpolators later.
Understanding the KeyFrame Class
A key frame defines the target state of a node at a specified point on the timeline. The target state is defined by the key values associated with the key frame.
An instant on the timeline
A set of KeyValues
A name
An ActionEvent handler
The instant on the timeline with which the key frame is associated is defined by a Duration, which is an offset of the key frame on the timeline.
The set of KeyValues defines the end value of the target for the key frame.
A key frame may optionally have a name that can be used as a cue point to jump to the instant defined by it during an animation. The getCuePoints() method of the Animation class returns a Map of cue points on the Timeline.
Optionally, you can attach an ActionEvent handler to a KeyFrame. The ActionEvent handler is called when the time for the key frame arrives during animation.
KeyFrame(Duration time, EventHandler<ActionEvent> onFinished, KeyValue... values)
KeyFrame(Duration time, KeyValue... values)
KeyFrame(Duration time, String name, EventHandler<ActionEvent> onFinished, Collection<KeyValue> values)
KeyFrame(Duration time, String name, EventHandler<ActionEvent> onFinished, KeyValue... values)
KeyFrame(Duration time, String name, KeyValue... values)
Understanding the Timeline Animation
Construct key frames.
Create a Timeline object with key frames.
Set the animation properties.
Use the play() method to run the animation.
You can add key frames to a Timeline at the time of creating it or after. The Timeline instance keeps all key frames in an ObservableList<KeyFrame> object. The getKeyFrames() method returns the list. You can modify the list of key frames at any time. If the timeline animation is already running, you need to stop and restart it to pick up the modified list of key frames.
Timeline()
Timeline(double targetFramerate)
Timeline(double targetFramerate, KeyFrame... keyFrames)
Timeline(KeyFrame... keyFrames)
The no-args constructor creates a Timeline with no key frames with animation running at the optimum rate. Other constructors let you specify the target frame rate for the animation, which is the number of frames per second, and the key frames.
Note that the order in which the key frames are added to a Timeline is not important. Timeline will order them based on their time offset.
Scrolling Text Using a Timeline Animation
The logic to perform the animation is in the start() method. The method starts with creating a Text object, a Pane with the Text object, and setting up a scene for the stage. After showing the stage, it sets up an animation.
The Timeline will create an initial key frame with the current value of the translateX property of the Text object, which is 0.0. This time, the Text scrolls differently. The scrolling starts by placing the Text at 0.0 and scrolling it to the left, so it goes beyond the scene.
Controlling an Animation
The Animation class contains properties and methods that can be used to control animation in various ways. The following sections will explain those properties and methods and how to use them to control animation.
Playing an Animation
play()
playFrom(Duration time)
playFrom(String cuePoint)
playFromStart()
The play() method plays an animation from its current position. If the animation was never started or stopped, it will play from the beginning. If the animation was paused, it will play from the position where it was paused. You can use the jumpTo(Duration time) and jumpTo(String cuePoint) methods to set the current position of the animation to a specific duration or a cue point, before calling the play() method. Calling the play() method is asynchronous. The animation may not start immediately. Calling the play() method while animation is running has no effect.
The playFrom() method plays an animation from the specified duration or the specified cue point. Calling this method is equivalent to setting the current position using the jumpTo() method and then calling the play() method.
The playFromStart() method plays the animation from the beginning (duration = 0).
Delaying the Start of an Animation
Stopping an Animation
Pausing an Animation
Use the pause() method to pause an animation. Calling this method when animation is not running has no effect. This method executes asynchronously. Calling the play() method when the animation is paused plays it from the current position. If you want to play the animation from the start, call the playFromStart() method .
Knowing the State of an Animation
Running
Paused
Stopped
Looping an Animation
Auto Reversing an Animation
By default, an animation runs only in the forward direction. For example, our scrolling text animation scrolled the text from right to left in one cycle. In the next cycle, the scrolling occurs again from right to left.
If you change the autoReverse, you need to stop and restart the animation for the new value to take effect.
Attaching an onFinished Action
Note that an animation with an Animation.INDEFINITE cycle count will not finish, and attaching such an action to the animation will never execute.
Knowing the Duration of an Animation
Duration to play one cycle of the animation
Duration to play all cycles of the animation
These durations are not set directly. They are set using other properties of the animation (cycle count, key frames, etc.).
The duration for one cycle is set using key frames. The key frame with the maximum duration determines the duration for one cycle when the animation is played at the rate 1.0. The read-only cycleDuration property of the Animation class reports the duration for one cycle.
The total duration for an animation is reported by the read-only totalDuration property. It is equal to cycleCount * cycleDuration. If the cycleCount is set to Animation.INDEFINITE, the totalDuration is reported as Duration.INDEFINITE.
Note that the actual duration for an animation depends on its play rate represented by the rate property. Because the play rate can be changed while animation is running, there is no easy way to compute the actual duration of an animation.
Adjusting the Speed of an Animation
The rate property of the Animation class specifies the direction and the speed for the animation. The sign of its value indicates the direction. The magnitude of the value indicates the speed. A positive value indicates the play in the forward direction. A negative value indicates the play in the backward direction. A value of 1.0 is considered the normal rate of play, a value of 2.0 double the normal rate, 0.50 half the normal rate, and so on. A rate of 0.0 stops the play.
The read-only currentRate property indicates the current rate (the direction and speed) at which the animation is playing. The values for the rate and currentRate properties may not be equal. The rate property indicates the rate at which the animation is expected to play when it runs, whereas the currentRate indicates the rate at which the animation is being played. When the animation is stopped or paused, the currentRate value is 0.0. If the animation reverses its direction automatically, the currentRate will report a different direction during reversal; for example, if the rate is 1.0, the currentRate reports 1.0 for the forward play cycle and –1.0 for the reverse play cycle.
Understanding Cue Points
You can set up cue points on a timeline. Cue points are named instants on the timeline. An animation can jump to a cue point using the jumpTo(String cuePoint) method. An animation maintains an ObservableMap<String,Duration> of cue points. The key in the map is the name of the cue points, and the values are the corresponding duration on the timeline. Use the getCuePoints() method to get the reference of the cue points map.
Giving a name to the KeyFrame you add to a timeline that adds a cue point in the cue point map
Adding name-duration pairs to the map returned by the getCuePoints() method of the Animation class
Tip Every animation has two predefined cue points: “start” and “end.” They are set at the start and end of the animation. The two cue points do not appear in the map returned by the getCuePoints() method.
Using Cue Points in Animation
Understanding Transitions
In the previous sections, you saw animations using a timeline that involved setting up key frames on the timeline. Using timeline animation is not easy in all cases. Consider moving a node in a circular path. Creating key frames and setting up a timeline to move the node on the circular path are not easy. JavaFX contains a number of classes (known as transitions) that let you animate nodes using predefined properties.
All transition classes inherit from the Transition class, which, in turn, inherits from the Animation class. All methods and properties in the Animation class are also available for use in creating transitions. The transition classes take care of creating the key frames and setting up the timeline. You need to specify the node, duration for the animation, and end values that are interpolated. Special transition classes are available to combine multiple animations that may run sequentially or in parallel.
The Transition class contains an interpolator property that specifies the interpolator to be used during animation. By default, it uses Interpolator.EASE_BOTH, which starts the animation slowly, accelerates it, and slows it down toward the end.
Understanding the Fade Transition
duration
node
fromValue
toValue
byValue
The duration property specifies the duration for one cycle of the animation.
The node property specifies the node whose opacity property is changed.
The fromValue property specifies the initial value for the opacity. If it is not specified, the current opacity of the node is used.
The toValue property specifies the opacity end value. The opacity of the node is updated between the initial value and the toValue for one cycle of the animation.
The byValue lets you set the opacity end value by incrementing or decrementing the initial value by an offset. If both toValue and byValue are specified, the toValue is used.
Suppose you want to set the initial and end opacity of a node between 1.0 and 0.5 in an animation. You can achieve it by setting the fromValue and toValue to 1.0 and 0.50 or by setting fromValue and byValue to 1.0 and –0.50.
The valid opacity value for a node is between 0.0 and 1.0. It is possible to set FadeTransition properties to exceed the range. The transition takes care of clamping the actual value in the range.
Creating a Fading Effect Using the FadeTransition Class
Understanding the Fill Transition
duration
shape
fromValue
toValue
The duration property specifies the duration for one cycle of the animation.
The shape property specifies the Shape whose fill property is changed.
The fromValue property specifies the initial fill color. If it is not specified, the current fill of the shape is used.
The toValue property specifies the fill end value.
The fill of the shape is updated between the initial value and the toValue for one cycle of the animation. The fill property in the Shape class is defined as a Paint. However, the fromValue and toValue are of the type Color. That is, the fill transition works for two Colors, not two Paints.
Creating a Fill Transition Using the FillTransition Class
Understanding the Stroke Transition
Understanding the Translate Transition
duration
node
fromX
fromY
fromZ
toX
toY
toZ
byX
byY
byZ
The duration property specifies the duration for one cycle of the animation.
The node property specifies the node whose translateX, translateY, and translateZ properties are changed.
The initial location of the node is defined by the (fromX, fromY, fromZ) value. If it is not specified, the current (translateX, translateY, translateZ) value of the node is used as the initial location.
The (toX, toY, toZ) value specifies the end location.
If both (toX, toY, toZ) and (byX, byY, byZ) values are specified, the former is used.
Creating a Translate Transition Using the TranslateTransition Class
Understanding the Rotate Transition
duration
node
axis
fromAngle
toAngle
byAngle
The duration property specifies the duration for one cycle of the animation.
The node property specifies the node whose rotate property is changed.
The axis property specifies the axis of rotation. If it is unspecified, the value for the rotationAxis property, which defaults to Rotate.Z_AXIS, for the node is used. The possible values are Rotate.X_AXIS, Rotate.Y_AXIS, and Rotate.Z_AXIS.
The initial angle for the rotation is specified by the fromAngle property. If it is unspecified, the value for the rotate property of the node is used as the initial angle.
The toAngle specifies the end rotation angle.
If both toAngle and byAngle values are specified, the former is used. All angles are specified in degrees. Zero degrees correspond to the 3 o’clock position. Positive values for angles are measured clockwise.
Creating a Rotate Transition Using the RotateTransition Class
Understanding the Scale Transition
duration
node
fromX
fromY
fromZ
toX
toY
toZ
byX
byY
byZ
The duration property specifies the duration for one cycle of the animation.
The node property specifies the node whose scaleX, scaleY, and scaleZ properties are changed.
The initial scale of the node is defined by the (fromX, fromY, fromZ) value. If it is not specified, the current (scaleX, scaleY, scaleZ) value of the node is used as the initial scale.
The (toX, toY, toZ) value specifies the end scale.
If both (toX, toY, toZ) and (byX, byY, byZ) values are specified, the former is used.
Creating a Scale Transition Using the ScaleTransition Class
Understanding the Path Transition
duration
node
path
orientation
The duration property specifies the duration for one cycle of the animation.
The node property specifies the node whose rotate property is changed.
The path property defines the path along which the node is moved. It is a Shape. You can use an Arc, a Circle, a Rectangle, an Ellipse, a Path, a SVGPath, and so on as the path.
PathTransition()
PathTransition(Duration duration, Shape path)
PathTransition(Duration duration, Shape path, Node node)
Creating a Path Transition Using the PathTransition Class
Understanding the Pause Transition
An instance of the PauseTransition class represents a pause transition. It causes a delay of the specified duration. Its use is not obvious. It is not used alone. Typically, it is used in a sequential transition to insert a pause between two transitions. It defines a duration property to specify the duration of the delay.
If you change the duration of a running pause transition, you need to stop and restart the transition to pick up the new duration. You will have an example when I discuss the sequential transition.
Understanding the Sequential Transition
An instance of the SequentialTransition class represents a sequential transition. It executes a list of animations in sequential order. The list of animations may contain timeline-based animations, transition-based animations, or both.
The SequentialTransition class contains a node property that is used as the node for animations in the list if the animation does not specify a node. If all animations specify a node, this property is not used.
A SequentialTransition maintains the animations in an ObservableList<Animation>. The getChildren() method returns the reference of the list.
The SequentialTransition class contains constructors that let you specify the list of animations and node.
It scales up the rectangle to double its size, and then down to the original size.
It changes the fill color of the rectangle from red to blue and then back to red.
It pauses for 200 milliseconds and then prints a message on the standard output.
It moves the rectangle along the outline of a circle.
The foregoing sequence of animations is repeated indefinitely.
Creating a Sequential Transition Using the SequentialTransition Class
Understanding the Parallel Transition
An instance of the ParallelTransition class represents a parallel transition. It executes a list of animations simultaneously. The list of animations may contain timeline-based animations, transition-based animations, or both.
The ParallelTransition class contains a node property that is used as the node for animations in the list if the animation does not specify a node. If all animations specify a node, this property is not used.
A ParallelTransition maintains the animations in an ObservableList<Animation>. The getChildren() method returns the reference of the list.
The ParallelTransition class contains constructors that let you specify the list of animations and node.
Creating a Parallel Transition Using the ParallelTransition Class
Understanding Interpolators
An interpolator is an instance of the abstract Interpolator class. An interpolator plays an important role in an animation. Its job is to compute the key values for the intermediate key frames during animation. Implementing a custom interpolator is easy. You need to subclass the Interpolator class and override its curve() method. The curve() method is passed the time elapsed for the current interval. The time is normalized between 0.0 and 1.0. The start and end of the interval have the value of 0.0 and 1.0, respectively. The value passed to the method would be 0.50 when half of the interval time has elapsed. The return value of the method indicates the fraction of change in the animated property.
The linear interpolator mandates that the percentage of change in the animated property is the same as the progression of the time for the interval.
Once you have a custom interpolator, you can use it in constructing key values for key frames in a timeline-based animation. For a transition-based animation, you can use it as the interpolator property of the transition classes.
Otherwise, if the animated property is an instance of the Interpolatable, it delegates the interpolation work to the interpolate() method of the Interpolatable. Otherwise, the interpolator defaults to a discrete interpolator by returning 1.0 when the time fraction is 1.0, and 0.0 otherwise.
Linear interpolator
Discrete interpolator
Ease-in interpolator
Ease-out interpolator
Ease-both interpolator
Spline interpolator
Tangent interpolator
Understanding the Linear Interpolator
The Interpolator.LINEAR constant represents a linear interpolator. It interpolates the value of the animated property of a node linearly with time. The percentage change in the property for an interval is the same as the percentage of the time passed.
Understanding the Discrete Interpolator
Using a Discrete Interpolator to Animate Hopping Text
Understanding the Ease-In Interpolator
The Interpolator.EASE_IN constant represents an ease-in interpolator. It starts the animation slowly for the first 20% of the time interval and accelerates afterward.
Understanding the Ease-Out Interpolator
The Interpolator.EASE_OUT constant represents an ease-out interpolator. It plays animation at a constant speed up to 80% of the time interval and slows down afterward.
Understanding the Ease-Both Interpolator
The Interpolator.EASE_BOTH constant represents an ease-both interpolator. Its plays the animation slower in the first 20% and the last 20% of the time interval and maintains a constant speed otherwise.
Understanding the Spline Interpolator
The Interpolator.SPLINE(double x1, double y1, double x2, double y2) static method returns a spline interpolator. It uses a cubic spline shape to compute the speed of the animation at any point in the interval. The parameters (x1, y1) and (x2, y2) define the control points of the cubic spline shape with (0, 0) and (1, 1) as implicit anchor points. The values of the parameters are between 0.0 and 1.0.
The slope at a given point on the cubic spline shape defines the acceleration at that point. A slope approaching the horizontal line indicates deceleration, whereas a slope approaching the vertical line indicates acceleration. For example, using (0, 0, 1, 1) as the parameters to the SPLINE method creates an interpolator with a constant speed, whereas the parameters (0.5, 0, 0.5, 1.0) will create an interpolator that accelerates in the first half and decelerates in the second half. Please refer to www.w3.org/TR/SMIL/smil-animation.html#animationNS-OverviewSpline for more details.
Understanding the Tangent Interpolator
The Interpolator.TANGENT static method returns a tangent interpolator, which defines the behavior of an animation before and after a key frame. All other interpolators interpolate data between two key frames. If you specify a tangent interpolator for a key frame, it is used to interpolate data before and after the key frame. The animation curve is defined in terms of a tangent, which is known as in-tangent, at a specified duration before the key frame and a tangent, which is called an out-tangent, at a specified duration after the key frame. This interpolator is used only in timeline-based animations as it affects two intervals.
Interpolator TANGENT(Duration t1, double v1, Duration t2, double v2)
Interpolator TANGENT(Duration t, double v)
In the first version, the parameters t1 and t2 are the duration before and after the key frame, respectively. The parameters v1 and v2 are the in-tangent and out-tangent values. That is, v1 is the tangent value at duration t1, and v2 is the tangent value at duration t2. The second version specifies the same value for both pairs.
Summary
In JavaFX, animation is defined as changing the property of a node over time. If the property that changes determines the location of the node, the animation in JavaFX will produce an illusion of motion. Not all animations have to involve motion; for example, changing the fill property of a Shape over time is an animation in JavaFX that does not involve motion.
Animation is performed over a period of time. A timeline denotes the progression of time during animation with an associated key frame at a given instant. A key frame represents the state of the node being animated at a specific instant on the timeline. A key frame has associated key values. A key value represents the value of a property of the node along with an interpolator to be used.
A timeline animation is used for animating any properties of a node. An instance of the Timeline class represents a timeline animation. Using a timeline animation involves the following steps: constructing key frames, creating a Timeline object with key frames, setting the animation properties, and using the play() method to run the animation. You can add key frames to a Timeline at the time of creating it or after. The Timeline instance keeps all key frames in an ObservableList<KeyFrame> object. The getKeyFrames() method returns the list. You can modify the list of key frames at any time. If the timeline animation is already running, you need to stop and restart it to pick up the modified list of key frames.
The Animation class contains several properties and methods to control animation such as playing, reversing, pausing, and stopping.
You can set up cue points on a timeline. Cue points are named instants on the timeline. An animation can jump to a cue point using the jumpTo(String cuePoint) method.
Using timeline animation is not easy in all cases. JavaFX contains a number of classes (known as transitions) that let you animate nodes using predefined properties. All transition classes inherit from the Transition class, which, in turn, inherits from the Animation class. The transition classes take care of creating the key frames and setting up the timeline. You need to specify the node, duration for the animation, and end values that are interpolated. Special transition classes are available to combine multiple animations that may run sequentially or in parallel. The Transition class contains an interpolator property that specifies the interpolator to be used during animation. By default, it uses Interpolator.EASE_BOTH, which starts the animation slowly, accelerates it, and slows it down toward the end.
An interpolator is an instance of the abstract Interpolator class. Its job is to compute the key values for the intermediate key frames during animation. JavaFX provides several built-in interpolators such as linear, discrete, ease-in, and ease-out. You can also implement a custom interpolator easily. You need to subclass the Interpolator class and override its curve() method. The curve() method is passed the time elapsed for the current interval. The time is normalized between 0.0 and 1.0. The return value of the method indicates the fraction of change in the animated property.
The next chapter will discuss how to incorporate different types of charts in a JavaFX application.