JavaFX graphics performance and suitability for advanced animations
Richard Bair
richard.bair at oracle.com
Fri May 31 20:59:32 PDT 2013
> This looks bad for me though in FX, I'm wondering what it looks like for you.
I ran with the pulse logger and definitely there is no frame taking more than a couple milliseconds. Things look awful because this example is truncating (by casting to int) instead of rounding, and so on each frame the rectangle is pixel snapped to a position that may be closer, or farther away from the expected location and our brain sees it. To test this theory, one thing I did was modify the sample so that instead of taking 3 seconds to travel 400 pixels, I use 4 seconds and I removed the EASE_BOTH interpolators. In this case the expected location on each frame is exactly a pixel boundary, and of course it looks smooth. Note though that the border still looks fuzzy (to me) but this is because the refresh rate on the monitor or possibly the eye is exhibiting a motion blur.
public void start(Stage stage) throws Exception {
final StackPane rootPane = new StackPane();
VBox box = new VBox();
box.setMaxSize(200, 200);
box.setStyle("-fx-border-color: black; -fx-background-color: white; -fx-effect: dropshadow(two-pass-box , darkgray, 10, 0.0 , 4, 5);");
rootPane.getChildren().add(box);
createTranslation(box, 4, -200, -200, 200, 200).play();
Scene scene = new Scene(rootPane, 1200, 800);
stage.setScene(scene);
stage.show();
}
protected Animation createTranslation(Node node, int seconds, int fromX, int fromY, int toX, int toY) {
IntegerProperty xProperty = new SimpleIntegerProperty(fromX);
IntegerProperty yProperty = new SimpleIntegerProperty(fromY);
node.translateXProperty().bind(xProperty);
node.translateYProperty().bind(yProperty);
Timeline t = new Timeline(
new KeyFrame(Duration.seconds(seconds),
new KeyValue(xProperty, toX),
new KeyValue(yProperty, toY)));
t.setCycleCount(Timeline.INDEFINITE);
t.setAutoReverse(true);
return t;
}
And here is another version which instead keeps the interpolator and the 3 second movement (so we're back to unexpected irregular positions) and we pixel snap by rounding instead of by truncating.
public void start(Stage stage) throws Exception {
final StackPane rootPane = new StackPane();
VBox box = new VBox();
box.setMaxSize(200, 200);
box.setStyle("-fx-border-color: black; -fx-background-color: white; -fx-effect: dropshadow(two-pass-box , darkgray, 10, 0.0 , 4, 5);");
rootPane.getChildren().add(box);
createTranslation(box, 3, -200, -200, 200, 200).play();
Scene scene = new Scene(rootPane, 1200, 800);
stage.setScene(scene);
stage.show();
}
class RoundingValue extends SimpleDoubleProperty {
public RoundingValue(int initialValue) {
super(initialValue);
}
@Override public void set(double newValue) {
super.set(Math.round(newValue));
}
}
protected Animation createTranslation(Node node, int seconds, int fromX, int fromY, int toX, int toY) {
RoundingValue xProperty = new RoundingValue(fromX);
RoundingValue yProperty = new RoundingValue(fromY);
node.translateXProperty().bind(xProperty);
node.translateYProperty().bind(yProperty);
Timeline t = new Timeline(
new KeyFrame(Duration.seconds(seconds),
new KeyValue(xProperty, toX, Interpolator.EASE_BOTH),
new KeyValue(yProperty, toY, Interpolator.EASE_BOTH)));
t.setCycleCount(Timeline.INDEFINITE);
t.setAutoReverse(true);
return t;
}
This looks pretty good perhaps this is what you are seeing in the browser?
Richard
More information about the openjfx-dev
mailing list