Animating Shapes Along a Path

By Peter Zhelezniakov, October 9, 2008

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.

Source Code
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.

Source Code
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.

Source Code
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.

Source Code
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) ,

Source Code
    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"
        } 
    );