Animation/Transition 的变化率
changing rate of Animation/Transition
我正在尝试制作一些基本的动画,但在最简单的事情上却失败了:
Rectangle rect = new Rectangle(100.0, 10.0);
mainPane.getChildren().add(rect); //so the rectangle is on screen
Animation anim = new Timeline(new KeyFrame(Duration.seconds(30.0),
new KeyValue(rect.widthProperty(), 0.0, Interpolator.LINEAR)));
rect.setOnMouseClicked(e -> {
if (anim.getStatus() == Status.RUNNING) {
anim.pause();
} else {
anim.setRate(Math.random() * 5.0);
anim.play();
System.out.println(anim.getRate());
}
});
我遇到的问题是,当我多次点击矩形时,大小会随机跳动,而不是改变它下降的速度。因此,例如,我让它 运行 以 ~2.5 的速度达到大约 50% 的大小,然后停止它。当我再次启动它时,它会跳到一个完全不同的大小,较小的速度较低,较大的速度较高,例如〜1.0速度为〜20%或〜4.5速度为〜80%。
一开始我以为动画是按照新的速度预先计算好的,所以就跳到了应该在的位置,如果之前已经播放的时间从头开始用新的速度播放的话停顿,但速度越慢,停顿越大,这在当时没有意义。
如何更改动画的 speed/rate 而不让它跳来跳去?
我认为您的诊断是正确的:当前值是在给定当前时间和当前速率的情况下内插得出的。如果您在不更改当前时间的情况下降低速率,那么您将在动画中更早。由于动画正在缩小,因此具有使矩形变大的效果。
最简单的方法可能就是每次都开始一个新的动画:
import javafx.animation.Animation;
import javafx.animation.Animation.Status;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class VariableRateAnimation extends Application {
private Animation anim ;
@Override
public void start(Stage primaryStage) {
Pane mainPane = new Pane();
Rectangle rect = new Rectangle(100.0, 10.0);
mainPane.getChildren().add(rect); //so the rectangle is on screen
rect.setOnMouseClicked(e -> {
if (anim != null && anim.getStatus() == Status.RUNNING) {
System.out.println("Paused (" + anim.getTotalDuration().subtract(anim.getCurrentTime())+ " remaining)");
anim.pause();
} else {
Duration duration = Duration.seconds(30.0 * rect.getWidth() / (100 * Math.random() * 5.0));
System.out.println("Starting: ("+duration+ " to go)");
double currentWidth = rect.getWidth() ;
if (anim != null) {
anim.stop();
}
anim = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(rect.widthProperty(), currentWidth, Interpolator.LINEAR)),
new KeyFrame(duration, new KeyValue(rect.widthProperty(), 0.0, Interpolator.LINEAR)));
anim.play();
}
});
primaryStage.setScene(new Scene(mainPane, 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我正在尝试制作一些基本的动画,但在最简单的事情上却失败了:
Rectangle rect = new Rectangle(100.0, 10.0);
mainPane.getChildren().add(rect); //so the rectangle is on screen
Animation anim = new Timeline(new KeyFrame(Duration.seconds(30.0),
new KeyValue(rect.widthProperty(), 0.0, Interpolator.LINEAR)));
rect.setOnMouseClicked(e -> {
if (anim.getStatus() == Status.RUNNING) {
anim.pause();
} else {
anim.setRate(Math.random() * 5.0);
anim.play();
System.out.println(anim.getRate());
}
});
我遇到的问题是,当我多次点击矩形时,大小会随机跳动,而不是改变它下降的速度。因此,例如,我让它 运行 以 ~2.5 的速度达到大约 50% 的大小,然后停止它。当我再次启动它时,它会跳到一个完全不同的大小,较小的速度较低,较大的速度较高,例如〜1.0速度为〜20%或〜4.5速度为〜80%。
一开始我以为动画是按照新的速度预先计算好的,所以就跳到了应该在的位置,如果之前已经播放的时间从头开始用新的速度播放的话停顿,但速度越慢,停顿越大,这在当时没有意义。
如何更改动画的 speed/rate 而不让它跳来跳去?
我认为您的诊断是正确的:当前值是在给定当前时间和当前速率的情况下内插得出的。如果您在不更改当前时间的情况下降低速率,那么您将在动画中更早。由于动画正在缩小,因此具有使矩形变大的效果。
最简单的方法可能就是每次都开始一个新的动画:
import javafx.animation.Animation;
import javafx.animation.Animation.Status;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class VariableRateAnimation extends Application {
private Animation anim ;
@Override
public void start(Stage primaryStage) {
Pane mainPane = new Pane();
Rectangle rect = new Rectangle(100.0, 10.0);
mainPane.getChildren().add(rect); //so the rectangle is on screen
rect.setOnMouseClicked(e -> {
if (anim != null && anim.getStatus() == Status.RUNNING) {
System.out.println("Paused (" + anim.getTotalDuration().subtract(anim.getCurrentTime())+ " remaining)");
anim.pause();
} else {
Duration duration = Duration.seconds(30.0 * rect.getWidth() / (100 * Math.random() * 5.0));
System.out.println("Starting: ("+duration+ " to go)");
double currentWidth = rect.getWidth() ;
if (anim != null) {
anim.stop();
}
anim = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(rect.widthProperty(), currentWidth, Interpolator.LINEAR)),
new KeyFrame(duration, new KeyValue(rect.widthProperty(), 0.0, Interpolator.LINEAR)));
anim.play();
}
});
primaryStage.setScene(new Scene(mainPane, 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}