user6685522
user6685522

Reputation:

RotationTransition Stopped in wrong angle JavaFX

I'm creating animation that will start rotating from left top corner to center of scene then go to right top corner and stop the rotation. Everything works fine but when it goes to top right corner it stop in wrong angle.

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.Group;
import javafx.animation.Animation;
import javafx.animation.RotateTransition;
import javafx.animation.KeyValue;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.Interpolator;
import javafx.util.Duration;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;



public class ComeWaitGo extends Application{
    @Override
    public void start(Stage stage){
        Rectangle box = new Rectangle(0, 0, 50, 50);
        RotateTransition rotate = new RotateTransition(Duration.millis(2000), box);
        rotate.setCycleCount(Animation.INDEFINITE);
        rotate.setByAngle(360);
        rotate.setInterpolator(Interpolator.LINEAR);
        rotate.play();


        KeyValue one = new KeyValue(box.xProperty(), 125);
        KeyValue two = new KeyValue(box.yProperty(), 100);

        KeyValue three = new KeyValue(box.xProperty(), 125);
        KeyValue four = new KeyValue(box.yProperty(), 100);

        KeyValue five = new KeyValue(box.xProperty(), 250);
        KeyValue six = new KeyValue(box.yProperty(), 0);

        EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>(){
            @Override
            public void handle(ActionEvent e){
                rotate.stop();
            }
        };

        KeyFrame frame = new KeyFrame(Duration.millis(3000), one, two);
        KeyFrame frametwo = new KeyFrame(Duration.millis(8000), three, four);
        KeyFrame framethree = new KeyFrame(Duration.millis(11000), stopRotate, five, six);
        Timeline timeline = new Timeline();
        timeline.getKeyFrames().addAll(frame, frametwo, framethree);
        timeline.play();



        Group root = new Group();
        root.getChildren().addAll(box);
        Scene scene = new Scene(root, 300, 250);
        stage.setScene(scene);
        stage.show();
    }
}

here

As you can see in image. when Rectangle goes to top right corner it not showing properly. ( Red line is just showing the path of rectangle (Image Editied))

So how I can get this animation? So the rectangle at the end should be in proper angle.

Upvotes: 1

Views: 491

Answers (2)

fabian
fabian

Reputation: 82461

Simply animate the rotate property of box using the timeline too, instead of using a seperate RotateTransition animation in addition to the Timeline animation:

KeyFrame framethree = new KeyFrame(Duration.millis(11000)
                                   /*, stopRotate*/,
                                  new KeyValue(box.rotateProperty(), 360d * 11000d / 2000d, Interpolator.LINEAR),
                                 five,
                                 six);

Alternatively combine both animations using a ParallelTransition to make sure both animations run synchronous:

// rotate.play();
...

Timeline timeline = new Timeline();

ParallelTransition transitions = new ParallelTransition(timeline, rotate);

EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent e) {
        transitions.stop();
    }
};
KeyFrame framethree = new KeyFrame(Duration.millis(11000), stopRotate, five, six);

timeline.getKeyFrames().addAll(frame, frametwo, framethree);
// timeline.play();
transitions.play();

complete start methods as requested

Approach 1:

@Override
public void start(Stage stage) {
    Rectangle box = new Rectangle(0, 0, 50, 50);

    KeyValue one = new KeyValue(box.xProperty(), 125);
    KeyValue two = new KeyValue(box.yProperty(), 100);

    KeyValue three = new KeyValue(box.xProperty(), 125);
    KeyValue four = new KeyValue(box.yProperty(), 100);

    KeyValue five = new KeyValue(box.xProperty(), 250);
    KeyValue six = new KeyValue(box.yProperty(), 0);

    KeyFrame frame = new KeyFrame(Duration.millis(3000), one, two);
    KeyFrame frametwo = new KeyFrame(Duration.millis(8000), three, four);
    KeyFrame framethree = new KeyFrame(Duration.millis(11000), five, six, new KeyValue(box.rotateProperty(), 360d * 11000d / 2000d, Interpolator.LINEAR));
    Timeline timeline = new Timeline();
    timeline.getKeyFrames().addAll(frame, frametwo, framethree);
    timeline.play();

    Group root = new Group();
    root.getChildren().addAll(box);
    Scene scene = new Scene(root, 300, 250);
    stage.setScene(scene);
    stage.show();
}

Approach 2:

@Override
public void start(Stage stage) {
    Rectangle box = new Rectangle(0, 0, 50, 50);
    RotateTransition rotate = new RotateTransition(Duration.millis(2000), box);
    rotate.setCycleCount(Animation.INDEFINITE);
    rotate.setByAngle(360);
    rotate.setInterpolator(Interpolator.LINEAR);

    KeyValue one = new KeyValue(box.xProperty(), 125);
    KeyValue two = new KeyValue(box.yProperty(), 100);

    KeyValue three = new KeyValue(box.xProperty(), 125);
    KeyValue four = new KeyValue(box.yProperty(), 100);

    KeyValue five = new KeyValue(box.xProperty(), 250);
    KeyValue six = new KeyValue(box.yProperty(), 0);


    KeyFrame frame = new KeyFrame(Duration.millis(3000), one, two);
    KeyFrame frametwo = new KeyFrame(Duration.millis(8000), three, four);
    Timeline timeline = new Timeline();

    ParallelTransition transitions = new ParallelTransition(timeline, rotate);

    EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent e) {
            transitions.stop();
        }
    };
    KeyFrame framethree = new KeyFrame(Duration.millis(11000), stopRotate, five, six);

    timeline.getKeyFrames().addAll(frame, frametwo, framethree);
    transitions.play();

    Group root = new Group();
    root.getChildren().addAll(box);
    Scene scene = new Scene(root, 300, 250);
    stage.setScene(scene);
    stage.show();
}

Upvotes: 2

trashgod
trashgod

Reputation: 205785

One approach would be to reset the box's rotation in stopRotate():

EventHandler<ActionEvent> stopRotate = new EventHandler<ActionEvent>(){
    @Override
    public void handle(ActionEvent e){
        rotate.stop();
        box.setRotate(0);
    }
};

Upvotes: 2

Related Questions