To play an Animation backwards from the end:
animation.setRate(negative rate);
animation.jumpTo(overall duration of animation);
animation.play();
But this does not play the same animation from the end.
Consider an animation that translates a node from 0 to 10:
Playing will translate the node from 0 to 10. Then doing the above will translate the node from 20 to 10, and not from 10 to 0.
Additionally, pausing the animation, setting rate = -1 and playing causes the animation to jump to the end.
[1] https://docs.oracle.com/javase/10/docs/api/javafx/animation/Animation.html#play()
--- Reproducer code ---
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.PauseTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AnimTest extends Application {
@Override
public void start(Stage stage) throws Exception {
var circle = new Circle(5, Color.BLUE);
var translateBy = new TranslateTransition(Duration.seconds(2), circle);
translateBy.setInterpolator(Interpolator.LINEAR);
translateBy.setFromX(0);
translateBy.setFromY(0);
translateBy.setByX(100);
translateBy.setByY(100);
VBox byPane = setup(translateBy, circle);
byPane.getChildren().add(0, new Label("By"));
var circle2 = new Circle(5, Color.BLUE);
var translateTo = new TranslateTransition(Duration.seconds(2), circle2);
translateTo.setInterpolator(Interpolator.LINEAR);
translateTo.setFromX(0);
translateTo.setFromY(0);
translateTo.setToX(100);
translateTo.setToY(100);
// translateTo.setAutoReverse(true);
// translateTo.setCycleCount(4);
VBox toPane = setup(translateTo, circle2);
toPane.getChildren().add(0, new Label("To"));
// translateTo.statusProperty().addListener((obs, ov, nv) -> System.out.println("status: " + ov + " -> " + nv));
translateTo.getCuePoints().put("A", null);
var root = new HBox(10, byPane, new Separator(Orientation.VERTICAL), toPane);
root.setPadding(new Insets(10));
stage.setScene(new Scene(root));
stage.show();
}
private VBox setup(Animation translate, Node node) {
var play = new Button("Play");
play.setOnAction(e -> translate.play());
var pause = new Button("Pause");
pause.setOnAction(e -> translate.pause());
var stop = new Button("Stop");
stop.setOnAction(e -> translate.stop());
var pauseTransition = new PauseTransition(Duration.millis(1));
pauseTransition.setOnFinished(e -> translate.pause());
var playPause = new Button("Play and pause");
playPause.setOnAction(e -> {
translate.play();
pauseTransition.play();
});
var jumpToStart = new Button("Jump to start");
jumpToStart.setOnAction(e -> translate.jumpTo("start"));
var jumpToEnd = new Button("Jump to end");
jumpToEnd.setOnAction(e -> translate.jumpTo("end"));
var rateP1 = new Button("rate=0.2");
rateP1.setOnAction(e -> translate.setRate(0.2));
var rateM1 = new Button("rate=-0.2");
rateM1.setOnAction(e -> translate.setRate(-0.2));
var rate0 = new Button("rate=0");
rate0.setOnAction(e -> translate.setRate(0));
var jump500 = new Button("jump to 500");
jump500.setOnAction(e -> translate.jumpTo(Duration.millis(500)));
var pane = new Pane(node);
pane.setPrefSize(400, 300);
var curTime = new Label();
curTime.textProperty().bind(translate.currentTimeProperty().asString());
var rate = new Label();
rate.textProperty().bind(translate.rateProperty().asString());
var curRate = new Label();
curRate.textProperty().bind(translate.currentRateProperty().asString());
var curState = new Label();
curState.textProperty().bind(translate.statusProperty().asString());
var controls = new VBox(5,
new HBox(5, play, pause, stop, playPause, curState),
new HBox(5, jumpToStart, jumpToEnd, jump500, curTime),
new HBox(5, rateP1, rateM1, rate0, rate, curRate));
var root = new VBox(10, pane, controls);
return root;
}
public static void main(String[] args) {
launch(args);
}
}
- blocks
-
JDK-8091172 Animation doesn't report its total current time including cycles or cycle number
- Open
- is blocked by
-
JDK-8236858 Animations do not play backwards after being paused
- In Progress
-
JDK-8237748 Animations with autoreverse do not play backwards after finishing
- In Progress
-
JDK-8237757 Animations do not play backwards after rate is set to 0
- In Progress
-
JDK-8237973 Animations do not jumpTo properly after setting a negative rate
- In Progress
-
JDK-8241237 Animations play in the wrong direction after jumpTo during a reverse cycle when paused
- In Progress
-
JDK-8236753 Animations do not play backwards after being stopped
- Resolved
-
JDK-8241582 Infinite animation does not start from the end when started with a negative rate
- Resolved
- relates to
-
JDK-8228570 Add various documentation clarifications
- Resolved
-
JDK-8228867 Fix mistakes in FX API docs
- Resolved
-
JDK-8250632 Update the docs of classes in the animation packages
- Open
-
JDK-8242523 Update the Animation and ClipEnvelope classes
- Resolved