Trying to interpolate a javafx Timeline with anticipation and overshooting, I've found the
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.