Animating Shapes Along a Path
This sample shows how to animate a shape along an arbitrary path. It has two "scenarios" that the user can switch between: a car running on a racetrack and a boat sailing on waves.
Note: This sample has customized the progress bar. Check out how, at the bottom of the page.
Understanding the Code
Path-based animation is provided by the class javafx.animation.transition.PathTransition. It takes two principal parameters: a Node that is animated and a Path along which the node moves.
When constructing a node to be animated, keep in mind that the center of the node always becomes the anchor point of the animation, i.e. the point that follows the path closely. An API to control the anchor point is planned in a future release, however, it is not there yet.
After both the node and the path are ready, animating is easily done. You specify the duration for the transition and the interpolation method. The optional ORTHOGONAL_TO_TANGENT parameter demands that the node be kept orthogonal to the tangent of the path. Otherwise, the car would stick in the initial left-to-right orientation and would not turn. Figure 1 shows the complete definition of the transition, taken from the sailboat scenario.
def path = Path {
...
};
def anim = PathTransition {
path: AnimationPath.createFromPath(path)
orientation: OrientationType.ORTHOGONAL_TO_TANGENT
node: ship
interpolator: Interpolator.LINEAR
duration: 8s
repeatCount: Timeline.INDEFINITE
};
Figure 1: Creating the Transition Object
To start the transition, use the play() method, as shown in Figure 2.
anim.play();
Figure 2: Starting the Transition
In the sailboat scenario, not only is the sailboat animated, but the waves also run from right to left. This effect is obtained with another type of transition, javafx.animation.transition.TranslateTransition. This transition is set up to travel the same distance as the PathTransition does, in the same time, but in the opposite direction so that the boat stays in the center of the scenario. Figure 3 shows the translating transition.
def move = TranslateTransition {
fromX: 0
fromY: 0
toX: -335*S
toY: 0
node: group
interpolator: Interpolator.LINEAR
duration: 8s
repeatCount: Timeline.INDEFINITE
};
Figure 3: Defining a Translation Transition
When the user switches between scenarios using the buttons in the top-left corner, the new scenario fades in. This is done using yet another transition class, javafx.animation.transition.FadeTransition. Its fromValue and toValue parameters refer to the opacity of the node. So in our case, illustrated by Figure 4, the scenario node is brought from its current opacity state to completely opaqueness in two seconds.
public abstract class Scenario extends Container {
var fadein = FadeTransition {
node: this
fromValue: bind this.opacity
toValue: 1
duration: 2s
interpolator: Interpolator.EASEOUT
};
var fadeout = FadeTransition {
node: this
fromValue: bind this.opacity
toValue: 0
duration: 2s
interpolator: Interpolator.EASEOUT
};
}
Figure 4: Using Fade Transition
Customizing Progress Bar
This sample demonstrates how to customize the default progress bar. You can add the custom progress bar with the different background image, the icon, and location of progress bar or icon.
The detault progress bar can be customized with the following attributes;
- Background image: progress.background.url
- Icon: progress.icon.url
- Location of an icon image: progress.icon.x, progress.icon.y
- Location of the progressbar: progress.bar.x, progress.bar.y
In this example, the background is a relative path to ../desc-resources/path_animation_bg.jpg. The custom icon is added to the relative directory ../desc-resources/boat.png, and the Y coordinate of the custom icon is set to "188". The location of progress bar is set to the coordinate (261, 21) ,
javafx(
{
archive: "webstart/PathAnimation.jar,",
width: 480,
height: 640,
code: "pathanimation.Main",
name: "appl"
} , {
"progress.background.url": "../desc-resources/path_animation_bg.jpg",
"progress.icon.url": "../desc-resources/boat.png",
"progress.icon.x": "261",
"progress.icon.y": "21",
"progress.bar.y": "188"
}
);

