【问题标题】:changing rate of Animation/Transition动画/过渡的变化率
【发布时间】:2015-07-28 12:51:35
【问题描述】:

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

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% 的大小,然后停止它。当我再次启动它时,它会跳到一个完全不同的大小,较小的速度较低,较大的速度较高,例如〜20%〜1.0速度或〜80%〜4.5速度。

起初我认为动画是针对新速度预先计算的,因此如果它从一开始就以新速度播放到暂停前已经播放的时间,它就会跳到它应该的位置,但速度越小,它就越大,这真的没有意义。

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

【问题讨论】:

    标签: animation javafx-8


    【解决方案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);
        }
    }
    

    【讨论】:

    • 旧动画会被正确地垃圾回收吗?既然只是暂停,那它可以随时继续吗?正如我所读到的,当不再需要动画时应该停止,但使用 anim.stop() 也会重置播放头,这不是我想要的。
    • 嗯。文档说“从 FX 运行时引用了正在运行的 Timeline。”我不知道“暂停”是否算作“正在运行”,但为了安全起见,也许最好打电话给stop()。查看更新的代码...
    猜你喜欢
    • 2011-05-05
    • 2012-03-17
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2016-02-26
    • 2016-11-01
    相关资源
    最近更新 更多