Home > database >  Javafx Interpolation anticipate/overshoot
Javafx Interpolation anticipate/overshoot

Time:10-21

Trying to interpolate a javafx Timeline with anticipation and overshooting, I've found the chrome interpolation curve editor

But what i'm getting is a RuntimeException

Caused by: java.lang.IllegalArgumentException: Control point coordinates must all be in range [0,1]
    at com.sun.scenario.animation.SplineInterpolator.<init>(SplineInterpolator.java:98)
    at javafx.animation.Interpolator.SPLINE(Interpolator.java:199)

Now my question is Why is it illegal to use Y values lower than 0 or greater than 1 in a SplineInterpolator, and what's the most convenient way to make an anticipate/overshoot interpolator in javafx ?

Adding a MRE

I'm trying to make transition between two nodes in a StackPane, using a timeline, but I need to interpolate it with anticipation/overshooting

public class App extends Application {

    @Override
    public void start(Stage ps) throws Exception {
        //Setting up the scene
        VBox root = new VBox();
        root.setBackground(new Background(new BackgroundFill(Color.GRAY, null, null)));
        
        StackPane cards = new StackPane();
        cards.setMinSize(600, 600);
        
        StackPane card1 = new StackPane(new Label("Card 1"));
        card1.setMaxSize(400, 200);
        card1.setBackground(new Background(new BackgroundFill(Color.WHITE, new CornerRadii(10), null)));
        
        StackPane card2 = new StackPane(new Label("Card 2"));
        card2.setMaxSize(200, 400);
        card2.setBackground(card1.getBackground());
        
        cards.getChildren().addAll(card1, card2);
        
        HBox buttons = new HBox(10);
        buttons.setPadding(new Insets(10));
        buttons.setAlignment(Pos.CENTER);
        
        Button show1 = new Button("Card 1");
        Button show2 = new Button("Card 2");
        
        buttons.getChildren().addAll(show1, show2);
        
        root.getChildren().addAll(cards, buttons);
        
        //adding behaviour
        double duration = .3;
        Interpolator interpolator = Interpolator.EASE_BOTH;
        
        Timeline showCard1 = new Timeline(new KeyFrame(Duration.seconds(duration), 
                new KeyValue(card1.opacityProperty(), 1, interpolator), 
                new KeyValue(card1.scaleXProperty(), 1, interpolator), 
                new KeyValue(card1.scaleYProperty(), 1, interpolator), 
                new KeyValue(card1.translateYProperty(), 0, interpolator),
                
                
                new KeyValue(card2.opacityProperty(), 0, interpolator), 
                new KeyValue(card2.scaleXProperty(), .5, interpolator), 
                new KeyValue(card2.scaleYProperty(), .5, interpolator), 
                new KeyValue(card2.translateYProperty(), -100, interpolator)
            ));
        
        Timeline showCard2 = new Timeline(new KeyFrame(Duration.seconds(duration), 
                new KeyValue(card2.opacityProperty(), 1, interpolator), 
                new KeyValue(card2.scaleXProperty(), 1, interpolator), 
                new KeyValue(card2.scaleYProperty(), 1, interpolator), 
                new KeyValue(card2.translateYProperty(), 0, interpolator),
                
                
                new KeyValue(card1.opacityProperty(), 0, interpolator), 
                new KeyValue(card1.scaleXProperty(), .5, interpolator), 
                new KeyValue(card1.scaleYProperty(), .5, interpolator), 
                new KeyValue(card1.translateYProperty(), -100, interpolator)
            ));
        
        show1.setOnAction(e-> {
            showCard2.stop();
            showCard1.playFromStart();
        });
        
        show2.setOnAction(e-> {
            showCard1.stop();
            showCard2.playFromStart();
        });
        
        show1.fire();
        
        Scene scene = new Scene(root);
        ps.setScene(scene);
        ps.show();
    }

}

(The example uses ease_both interpolation because attempting to use spline curve with values out of range gives the error described above)

CodePudding user response:

Why is it illegal to use Y values lower than 0 or greater than 1 in a SplineInterpolator,

I don’t know.

and what's the most convenient way to make an anticipate/overshoot interpolator in javafx ?

Create your own implementation.

Extend Interpolator, don’t use a range check in your implementation, unit test it to ensure it performs the functionality you want.

Example implementation you might wish to start from.

  • Related