在时间轴中同时播放JavaFX动画

lnlaulya  于 2023-11-15  发布在  Java
关注(0)|答案(2)|浏览(146)

我对JavaFX还很陌生。我正在尝试制作这个时间轴,其中每个关键帧都在前一个关键帧完成后发生。到目前为止,每个步骤都按照我的要求一个接一个地发生。然而,我一播放动画,rotateBack关键帧就开始旋转我的对象。关于如何使rotateBack只在moveToRight之后播放,有什么提示吗?此外,我想为rotateBack完成其旋转前moveToTop播放。谢谢。

Pane selectedPane = select_pane.getValue();
                    
    double rootWidth = root_pane.getWidth();
    double rootHeight = root_pane.getHeight();
    double sixthWidth = rootWidth / 6;

    KeyValue moveTopLeftX = new KeyValue(selectedPane.layoutXProperty(), 0);
    KeyValue moveDownY = new KeyValue(selectedPane.layoutYProperty(), root_pane.getHeight()                   -    selectedPane.getHeight());

    KeyValue moveRightX = new KeyValue(selectedPane.layoutXProperty(), sixthWidth);
    KeyValue rotate180 = new KeyValue(selectedPane.rotateProperty(), 180);
    KeyValue moveToTopY = new KeyValue(selectedPane.layoutYProperty(), 0);

    KeyFrame startFrame = new KeyFrame(Duration.seconds(3), moveTopLeftX, moveToTopY);
    KeyFrame moveToRight = new KeyFrame(Duration.seconds(2), moveRightX);
    KeyFrame rotateBack = new KeyFrame(Duration.seconds(3), rotate180);
    KeyFrame moveToBottom = new KeyFrame(Duration.seconds(6), moveDownY);
    KeyFrame moveToTop = new KeyFrame(Duration.seconds(6), moveToTopY);

    Timeline timeline = new Timeline(startFrame, moveToBottom, moveToRight, rotateBack, moveToTop);

    timeline.play();

字符串
到目前为止,我所尝试的是在上面的代码中显示。任何提示非常感谢。

juud5qan

juud5qan1#

要在一个关键帧完成后才播放一个关键帧,您可以创建不同的时间轴,并在时间轴.setOnFinished()函数中播放下一个。
对于你的例子,它看起来像这样:

Pane selectedPane = select_pane.getValue();
                
double rootWidth = root_pane.getWidth();
double rootHeight = root_pane.getHeight();
double sixthWidth = rootWidth / 6;

KeyValue moveTopLeftX = new KeyValue(selectedPane.layoutXProperty(), 0);
KeyValue moveDownY = new KeyValue(selectedPane.layoutYProperty(), root_pane.getHeight()                   -    selectedPane.getHeight());

KeyValue moveRightX = new KeyValue(selectedPane.layoutXProperty(), sixthWidth);
KeyValue rotate180 = new KeyValue(selectedPane.rotateProperty(), 180);
KeyValue moveToTopY = new KeyValue(selectedPane.layoutYProperty(), 0);

KeyFrame startFrame = new KeyFrame(Duration.seconds(3), moveTopLeftX, moveToTopY);
KeyFrame moveToRight = new KeyFrame(Duration.seconds(2), moveRightX);
KeyFrame rotateBack = new KeyFrame(Duration.seconds(3), rotate180);
KeyFrame moveToBottom = new KeyFrame(Duration.seconds(6), moveDownY);
KeyFrame moveToTop = new KeyFrame(Duration.seconds(6), moveToTopY);

Timeline timelineStart = new Timeline(startFrame, moveToBottom, moveToRight);

Timeline timelineRotateBack = new Timeline(rotateBack);

Timeline timelineMoveToTop = new Timeline(moveToTop);

timelineStart.setOnFinished(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                timelineRotateBack.play();
            }
        });

timelineRotateBack.setOnFinished(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                timelineMoveToTop.play();
            }
        });

timelineStart.play();

字符串
在这里,它将播放所有这些关键帧(startFrame,moveToBottom,moveToRight)第一,当所有动画完成时,它将播放rotateBack KeyFrame,当这一个完成时,它将播放moveToTop

hmtdttj4

hmtdttj42#

过渡是解决这个问题的好方法

提供了一个基于SequentialTransition而不是Timeline的示例。您可以使用Timeline来代替,正如其他评论或答案中所指出的那样。然而,对于您描述的功能,使用transitions似乎更适合。
该示例对TranslateTransitionRotateTransition类型的各种事务进行排序,以执行所需的动画。
如果您希望部分序列并行执行,那么您可以对这些部分使用ParallelTransition(如果需要,可以组合并行和顺序转换)。

动画使用translate属性

在执行动画时,应该使用translate X/Y/Z属性,而不是layoutX/Y属性。虽然您可以对布局更改进行动画处理,但这是一个高级主题,不建议对JavaFX新手使用。这里提供的示例基于translate属性,而不是layout属性。

选择合适的插值器

关键帧的默认插值器是LINEAR,过渡的默认插值器是EASE_BOTH。通过在关键帧或过渡上设置插值器来选择适合您应用程序的插值器。对于这个例子,我觉得过渡的默认EASE_BOTH插值是最合适的,从而产生更平滑的动画感觉。

示例代码

import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.io.IOException;

public class TransitionApp extends Application {
    private static final Color INDIA_INK = Color.web("#3d3f4a");
    private static final double W = 400, H = 400;
    private static final double BOX_W = 20, BOX_H = 20;
    private static final double BOX_TOP_SIDE_INDICATOR_H = 3;
    private static final double MOVE_STEP = 50;
    private static final Duration TIME_STEP = Duration.seconds(3);

    public void start(Stage stage) throws IOException {
        Group box = createBox(BOX_W, BOX_H, BOX_TOP_SIDE_INDICATOR_H);
        box.setTranslateX(W / 2 - BOX_W / 2);
        box.setTranslateY(H / 2 - BOX_H / 2);

        Pane root = new Pane(box);
        root.setBackground(Background.fill(INDIA_INK));
        root.setPrefSize(W, H);

        stage.setResizable(false);
        stage.setScene(new Scene(root));
        stage.show();

        SequentialTransition transition = createTransition(box);
        transition.play();
    }

    private SequentialTransition createTransition(Group box) {
        TranslateTransition moveToTopLeft = new TranslateTransition(TIME_STEP);
        moveToTopLeft.setToX(0);
        moveToTopLeft.setToY(0);

        TranslateTransition moveToBottom = new TranslateTransition(TIME_STEP.multiply(2));
        moveToBottom.setToY(H - BOX_H);

        TranslateTransition moveRight = new TranslateTransition(TIME_STEP);
        moveRight.setToX(MOVE_STEP);

        RotateTransition rotate180 = new RotateTransition(TIME_STEP);
        rotate180.setByAngle(180);

        TranslateTransition moveToTop = new TranslateTransition(TIME_STEP.multiply(2));
        moveToTop.setToY(0);

        SequentialTransition sequentialTransition = new SequentialTransition(
                box,
                moveToTopLeft, moveToBottom, moveRight, rotate180, moveToTop
        );
        sequentialTransition.setAutoReverse(true);
        sequentialTransition.setCycleCount(Transition.INDEFINITE);
        
        return sequentialTransition;
    }

    private static Group createBox(double w, double h, double topSideIndicatorH) {
        Rectangle rectangle = new Rectangle(
                w, h, Color.GREEN
        );

        Rectangle topLine = new Rectangle(
                w, topSideIndicatorH, Color.RED
        );

        return new Group(
                rectangle, topLine
        );
    }

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

字符串

相关问题