How to create JavaFX Transition with Equally-Timed Elements?

别说谁变了你拦得住时间么 提交于 2020-01-15 02:47:09

问题


I'm experimenting with JavaFX and animations, especially PathTransition. I'm creating a simple program that makes a ball "bounce," without using the QuadCurveTo class. Here is my code so far:

Ellipse ball = new Ellipse(375, 250, 10, 10);
root.getChildren().add(ball);

Path path = new Path();
path.getElements().add(new MoveTo(375, 500));

int posX = 375;
int posY = 500;
int changeX = 10;
int changeY = 50;
int gravity = 10; // approximate in m/s^2
int sec = 0;

for(; posY<=500; sec++, posX-=changeX, posY-=changeY, changeY-=gravity)
    path.getElements().add(new LineTo(posX, posY));
    // How do I equally space these elements?

PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(sec*1000));
pathTransition.setNode(ball);
pathTransition.setAutoReverse(true);
pathTransition.setCycleCount(Timeline.INDEFINITE);
pathTransition.setInterpolator(Interpolator.LINEAR);
pathTransition.setPath(path);
pathTransition.play();

I have the for loop running through a quadratic sequence, and the ball moves in the correct motion (a curved path).

However, I want it to move slower at the top of the curve (vertex) because it is moving less distance (as changeY, the vertical increment variable, is decreasing as the loop goes on) to simulate a more realistic curve. However, it is traveling in a linear speed throughout the full time.

Is there any way to make each of the elements equally spaced (throughout) time, so that this "bounce" would show correctly? Thanks.


回答1:


I wouldn't use a timeline or transition at all for this. Use an AnimationTimer and compute the new coordinates based on the elapsed time since the last frame. The AnimationTimer has a handle method which is invoked once per rendering frame, taking a value that represents a timestamp in nanoseconds.

SSCCE (with elasticity added to the physics):

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class BouncingBall extends Application {

    @Override
    public void start(Stage primaryStage) {
        Circle ball = new Circle(20, 80, 10);
        ball.setFill(Color.DARKBLUE);
        Pane pane = new Pane(ball);

        AnimationTimer timer = new AnimationTimer() {

            long lastUpdate = 0 ;
            double changeX = 0.1 ;
            double changeY = 0 ;
            double gravity = 10 ;
            double elasticity = 0.95 ;

            @Override
            public void handle(long now) {
                if (lastUpdate == 0) {
                    lastUpdate = now ;
                    return ;
                }
                long elapsedNanos = now - lastUpdate;
                double elapsedSeconds = elapsedNanos / 1_000_000_000.0 ;
                lastUpdate = now ;
                ball.setCenterX(ball.getCenterX() + changeX);
                if (ball.getCenterY() + changeY + ball.getRadius() >= pane.getHeight()) {
                    changeY = - changeY * elasticity;
                } else {
                    changeY = changeY + gravity * elapsedSeconds ;
                }
                ball.setCenterY(Math.min(ball.getCenterY() + changeY, pane.getHeight() - ball.getRadius()));
            }

        };

        primaryStage.setScene(new Scene(pane, 400, 400));
        primaryStage.show();
        timer.start();
    }

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


来源:https://stackoverflow.com/questions/31463653/how-to-create-javafx-transition-with-equally-timed-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!