动画/过渡的变化率

时间:2015-07-28 12:51:35

标签: animation javafx-8

我试图做一些基本的动画,但是在最简单的事情上失败了:

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%。

起初我认为动画是针对新速度预先计算出来的,因此跳到了原来的位置,如果它从开始时的新速度播放到暂停之前已经播放的时间但是对于较小的速度来说它更大,这当然没有意义。

如何在不跳过动画的情况下更改动画的速度/速率?

1 个答案:

答案 0 :(得分:1)

我认为您的诊断是正确的:在给定当前时间和当前速率的情况下对当前值进行插值。如果在不改变当前时间的情况下降低速率,则可以在动画中更早。由于动画正在缩小,这会使矩形变大。

最简单的方法可能就是每次都开始一个新动画:

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);
    }
}