关键帧之间的 JavaFx 动画延迟
JavaFx Animation delay between keyframes
我有一个小代码片段来启动场景之间的过渡动画:
static void initClosingAnimation() {
ObservableList<Node> components = window.getScene().getRoot().getChildrenUnmodifiable();
time = new Timeline();
for (Node component : components) {
KeyValue keyvalue = new KeyValue(component.translateXProperty(), window.getWidth(), Interpolator.EASE_OUT);
KeyFrame keyframe = new KeyFrame(Duration.seconds(0.4), keyvalue);
time.getKeyFrames().add(keyframe);
}
time.play();
}
该代码从一个场景中获取所有现有组件,然后向每个组件添加一个单独的关键帧,以创建从左到右的过渡。然而,通过这种方式,每个组件都在完全相同的时间移动,这不是我对这个功能的想法。
是否有一种干净的方法可以在每个关键帧之间添加一个小的延迟,以便每个组件一个接一个地淡出,或者甚至可以按照我的想法进行?
只是每个组件使用不同的时间点:
void initClosingAnimation() {
ObservableList<Node> components = window.getScene().getRoot().getChildrenUnmodifiable();
time = new Timeline();
Duration startTime = Duration.ZERO ;
Duration endTime = Duration.seconds(0.4);
Duration offset = Duration.seconds(0.1);
for (Node component : components) {
KeyValue startValue = new KeyValue(component.translateXProperty(), component.getTranslateX(), Interpolator.EASE_OUT);
KeyValue endValue = new KeyValue(component.translateXProperty(), window.getWidth(), Interpolator.EASE_OUT);
KeyFrame start = new KeyFrame(startTime, startValue);
KeyFrame end = new KeyFrame(endTime, endValue);
time.getKeyFrames().add(start);
time.getKeyFrames().add(end);
startTime = startTime.add(offset);
endTime = endTime.add(offset);
}
time.play();
}
这是一个完整的例子(对上面的方法签名稍作修改):
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.Duration;
public class App extends Application {
@Override
public void start(Stage stage) {
VBox root = new VBox(5);
root.setAlignment(Pos.CENTER);
for (int i = 1 ; i <= 10 ; i++) root.getChildren().add(new Label("Item "+i));
Button close = new Button("Close");
root.getChildren().add(close);
close.setOnAction(e -> initClosingAnimation(stage, stage::hide));
Scene scene = new Scene(root, 400, 600);
stage.setScene(scene);
stage.setOnCloseRequest(e -> {
initClosingAnimation(stage, stage::hide);
e.consume();
});
stage.show();
}
private void initClosingAnimation(Window window, Runnable onFinished) {
ObservableList<Node> components = window.getScene().getRoot().getChildrenUnmodifiable();
Timeline time = new Timeline();
Duration startTime = Duration.ZERO ;
Duration endTime = Duration.seconds(0.4);
Duration offset = Duration.seconds(0.1);
for (Node component : components) {
KeyValue startValue = new KeyValue(component.translateXProperty(), component.getTranslateX(), Interpolator.EASE_OUT);
KeyValue endValue = new KeyValue(component.translateXProperty(), window.getWidth(), Interpolator.EASE_OUT);
KeyFrame start = new KeyFrame(startTime, startValue);
KeyFrame end = new KeyFrame(endTime, endValue);
time.getKeyFrames().add(start);
time.getKeyFrames().add(end);
startTime = startTime.add(offset);
endTime = endTime.add(offset);
}
time.setOnFinished(e -> onFinished.run());
time.play();
}
public static void main(String[] args) {
launch();
}
}
我有一个小代码片段来启动场景之间的过渡动画:
static void initClosingAnimation() {
ObservableList<Node> components = window.getScene().getRoot().getChildrenUnmodifiable();
time = new Timeline();
for (Node component : components) {
KeyValue keyvalue = new KeyValue(component.translateXProperty(), window.getWidth(), Interpolator.EASE_OUT);
KeyFrame keyframe = new KeyFrame(Duration.seconds(0.4), keyvalue);
time.getKeyFrames().add(keyframe);
}
time.play();
}
该代码从一个场景中获取所有现有组件,然后向每个组件添加一个单独的关键帧,以创建从左到右的过渡。然而,通过这种方式,每个组件都在完全相同的时间移动,这不是我对这个功能的想法。
是否有一种干净的方法可以在每个关键帧之间添加一个小的延迟,以便每个组件一个接一个地淡出,或者甚至可以按照我的想法进行?
只是每个组件使用不同的时间点:
void initClosingAnimation() {
ObservableList<Node> components = window.getScene().getRoot().getChildrenUnmodifiable();
time = new Timeline();
Duration startTime = Duration.ZERO ;
Duration endTime = Duration.seconds(0.4);
Duration offset = Duration.seconds(0.1);
for (Node component : components) {
KeyValue startValue = new KeyValue(component.translateXProperty(), component.getTranslateX(), Interpolator.EASE_OUT);
KeyValue endValue = new KeyValue(component.translateXProperty(), window.getWidth(), Interpolator.EASE_OUT);
KeyFrame start = new KeyFrame(startTime, startValue);
KeyFrame end = new KeyFrame(endTime, endValue);
time.getKeyFrames().add(start);
time.getKeyFrames().add(end);
startTime = startTime.add(offset);
endTime = endTime.add(offset);
}
time.play();
}
这是一个完整的例子(对上面的方法签名稍作修改):
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.Duration;
public class App extends Application {
@Override
public void start(Stage stage) {
VBox root = new VBox(5);
root.setAlignment(Pos.CENTER);
for (int i = 1 ; i <= 10 ; i++) root.getChildren().add(new Label("Item "+i));
Button close = new Button("Close");
root.getChildren().add(close);
close.setOnAction(e -> initClosingAnimation(stage, stage::hide));
Scene scene = new Scene(root, 400, 600);
stage.setScene(scene);
stage.setOnCloseRequest(e -> {
initClosingAnimation(stage, stage::hide);
e.consume();
});
stage.show();
}
private void initClosingAnimation(Window window, Runnable onFinished) {
ObservableList<Node> components = window.getScene().getRoot().getChildrenUnmodifiable();
Timeline time = new Timeline();
Duration startTime = Duration.ZERO ;
Duration endTime = Duration.seconds(0.4);
Duration offset = Duration.seconds(0.1);
for (Node component : components) {
KeyValue startValue = new KeyValue(component.translateXProperty(), component.getTranslateX(), Interpolator.EASE_OUT);
KeyValue endValue = new KeyValue(component.translateXProperty(), window.getWidth(), Interpolator.EASE_OUT);
KeyFrame start = new KeyFrame(startTime, startValue);
KeyFrame end = new KeyFrame(endTime, endValue);
time.getKeyFrames().add(start);
time.getKeyFrames().add(end);
startTime = startTime.add(offset);
endTime = endTime.add(offset);
}
time.setOnFinished(e -> onFinished.run());
time.play();
}
public static void main(String[] args) {
launch();
}
}