【问题标题】:How to reverse animation after it has finished?完成后如何反转动画?
【发布时间】:2019-01-24 10:02:50
【问题描述】:

我有一个动画列表,我希望能够通过单击“下一个”按钮来播放它们,并通过单击“上一个”按钮来播放它们。所以我可以播放第一个动画,然后播放第二个动画,然后向后播放第二个动画,并到达播放第一个动画后的位置。

我的问题是动画完成后我无法反转动画。我知道我可以设置autoReverse,但随后每个动画都会立即反转。

这是一个动画的示例:

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
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 {
        Circle c = new Circle(5, Color.RED);
        TranslateTransition move = new TranslateTransition(Duration.seconds(2), c);
        move.setByX(10);
        move.setByY(10);

        Button next = new Button("Next");
        Button previous = new Button("Previous");
        next.setOnAction(e -> {
            move.setRate(1);
            move.play();
        });
        previous.setOnAction(e -> {
            move.setRate(-1);
            move.play();
        });

        Pane p = new Pane(c);
        p.setPrefSize(50, 50);
        HBox buttons = new HBox(next, previous);
        VBox root = new VBox(p, buttons);
        stage.setScene(new Scene(root));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

按“下一个”后,我希望“上一个”将球移回其原始位置(因此有效地 x x -10 和 y x -10),而不是反向播放“跟随”动画。

在实践中,我的动画为场景图中的不同对象设置动画,它们可以是并行/顺序转换。对于列表,我保留当前位置索引i 并执行以下操作:

    next.setOnAction(e -> {
        Animation move = list.get(i);
        move.setRate(1);
        move.play();
        i++;
    });
    previous.setOnAction(e -> {
        i--;
        Animation move = list.get(i);
        move.setRate(-1);
        move.play();
    });

试图反转之前的动画。

我该怎么做?

为了澄清,我的名单是AnimationTranslateTransition 只是一个例子。

【问题讨论】:

    标签: java animation javafx


    【解决方案1】:

    这里的问题是使用“相对”运动而不是绝对运动。

    如果您设置byX = 10,则动画在向前播放时将节点10向右移动,这意味着反转动画的正确方法是立即将节点放置在结束位置,然后将节点移回原来的位置开始动画之前的位置。

    由于您不想一遍又一遍地使用相同的动画,因此对于使用“相对”值的动画来说,找到反转不同动画的正确方法可能会很困难。如果您改为使用绝对动画,这不应该只是简单地向后播放动画不会导致任何问题。

    示例

    @Override
    public void start(Stage stage) {
        Circle c = new Circle(5, Color.RED);
    
        // create alternating right/down movement animations with absolute movement
        List<Animation> animations = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            TranslateTransition move = new TranslateTransition(Duration.seconds(1), c);
            animations.add(move);
            int step = i >> 1;
            if ((i & 1) == 0) {
                move.setFromX(step * 10);
                move.setToX((step + 1) * 10);
            } else {
                move.setFromY(step * 10);
                move.setToY((step + 1) * 10);
            }
        }
    
        final ListIterator<Animation> iterator = animations.listIterator();
        
        Button next = new Button("Next");
        Button previous = new Button("Previous");
        previous.setDisable(true);
        
        next.setOnAction(e -> {
            Animation move = iterator.next();
            
            next.setDisable(!iterator.hasNext());
            previous.setDisable(false);
            
            move.setRate(1);
            move.play();
        });
        
        previous.setOnAction(e -> {
            Animation move = iterator.previous();
            
            next.setDisable(false);
            previous.setDisable(!iterator.hasPrevious());
            
            move.setRate(-1);
            move.play();
        });
    
        Pane p = new Pane(c);
        p.setPrefSize(100, 100);
        HBox buttons = new HBox(next, previous);
        VBox root = new VBox(p, buttons);
        stage.setScene(new Scene(root));
        stage.show();
    }
    

    【讨论】:

    • 所以对于一般动画(正如我所说的我的通常是顺序和并行过渡),这是不可能的吗? autoReverse 的第二个循环执行此操作。我想知道是否可以“捕获并存储”第二个(反向)循环并稍后播放。如果动画可以内置,我不应该也可以吗?
    • @Mark 为什么不可能?只要SequentialTransitionParallelTransition 的所有部分都是“绝对的”,而不是“相对的”,这应该可以工作。 autoReverse 和您的代码之间的区别在于 Transitions“知道”如何正确反转自己,但假设您想要完全控制动画播放的方向,您需要自行实现此逻辑 (@987654327 @ 需要与TranslateTransitions 不同的反转逻辑。
    • 我的意思是这只适用于我自己知道如何在数学上反转的动画,是绝对的,我需要提前准备。给定Animation的列表,能做到吗?
    • 如果你有兴趣,我设法用一个技巧解决了这个问题。如果你想看看我会appriciate它。
    【解决方案2】:

    我设法使用PauseTransition 欺骗我的方式“存储”反向循环以供以后使用,该PauseTransition 在正向循环之后暂停动画。然后动画可以从第二个循环开始播放,它会反转。不是最漂亮的解决方案,但它可以工作(除非你按下按钮太快。我试图用评论代码解决它,但它并没有完全到达那里,所以如果有人有解决方案,请告诉)

    import java.util.ArrayList;
    import java.util.List;
    
    import javafx.animation.Animation;
    import javafx.animation.ParallelTransition;
    import javafx.animation.PauseTransition;
    import javafx.animation.TranslateTransition;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    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 {
    
        int current = 0;
        final int size = 5;
    
        @Override
        public void start(Stage stage) throws Exception {
            Circle c = new Circle(10, Color.RED);
    
            List<Animation> animations = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                TranslateTransition move = new TranslateTransition(Duration.seconds(1), c);
                move.setByX(20);
                move.setByY(20);
                PauseTransition pauser = new PauseTransition(move.getCycleDuration());
                ParallelTransition parallel = new ParallelTransition(move, pauser);
                pauser.setOnFinished(e -> parallel.pause());
                parallel.setCycleCount(2);
                parallel.setAutoReverse(true);
                animations.add(parallel);
            }
    
            Button next = new Button("Next");
            Button previous = new Button("Previous");
            previous.setDisable(true);
    
            Label l = new Label(current + "");
    
            next.setOnAction(e -> {
                next.setDisable(current == size - 1);
                previous.setDisable(false);
    
    /*          if (current > 0) {
                    Animation last = animations.get(current - 1);
                    last.jumpTo(last.getCycleDuration());
                }*/
                Animation cur = animations.get(current);
                cur.playFromStart();
    
                current++;
                l.setText(current + "");
            });
    
            previous.setOnAction(e -> {
                current--;
                l.setText(current + "");
    
                next.setDisable(false);
                previous.setDisable(current == 0);
    
    /*          if (current < size - 1) {
                    Animation last = animations.get(current + 1);
                    last.stop();
                }*/
                Animation cur = animations.get(current);
                cur.play();
            });
    
            Pane p = new Pane(c);
            p.setPrefSize(200, 200);
            HBox buttons = new HBox(5, next, previous, l);
            VBox root = new VBox(p, buttons);
            stage.setScene(new Scene(root));
            stage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    我使用了 fabian (+1) 的禁用/启用按钮代码。

    【讨论】:

      【解决方案3】:

      要在 java 中反转动画,首先必须将动画的 autoReverse 属性设置为 true,并将 cycleCount 设置为 2。 下面是我之前写的一个简单的代码sn-p,它利用了上面提到的东西。

          ScaleTransition scaleTransition = new ScaleTransition(duration, btn);
          scaleTransition.setByX(1.2);
          scaleTransition.setByY(1.2);
          scaleTransition.setAutoReverse(true);
          scaleTransition.setCycleCount(2);
          scaleTransition.play();
      

      【讨论】:

        猜你喜欢
        • 2017-06-08
        • 2015-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-16
        相关资源
        最近更新 更多