我正在编写一些 javaFX 代码,并且已将一些路径添加到组中,该组已添加到另一个组中,该组已添加到根目录并显示在屏幕上。现在在某个时刻,我想使用 PathTransition 将这个最低级别的组动画到一个新位置。我无法确定过渡的正确坐标。我已经读过 PathTransition 将从其中心而不是左上角为节点设置动画,因此我尝试将 Group.getLayoutX()/2 添加到起始 x 并将 Group.getLayoutY()/2 添加到起始 y 坐标但是在动画开始之前,它似乎仍然使组跳到新的起始位置。最终目的地似乎也有点偏离。有没有更好的方法来为包含多个路径的组设置动画?
问问题
2429 次
1 回答
0
根据正在动画的节点的布局边界的一半调整节点跟随路径的layoutX
和。layoutY
rect.setLayoutX(rect.getLayoutX() + rect.getLayoutBounds().getWidth() / 2);
rect.setLayoutY(rect.getLayoutY() + rect.getLayoutBounds().getHeight() / 2);
尝试从JavaFX 2 circle path for animation修改 Uluk 的圆形路径过渡代码。
代码将使节点原始布局的左上角跟随路径。
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;
public class ArcToDemo extends Application {
private PathTransition pathTransitionEllipse;
private PathTransition pathTransitionCircle;
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root, 600, 460));
// Ellipse path example
Rectangle rect = new Rectangle(0, 0, 40, 40);
rect.setArcHeight(10);
rect.setArcWidth(10);
rect.setFill(Color.ORANGE);
root.getChildren().add(rect);
Path path = createEllipsePath(200, 200, 50, 100, 45);
root.getChildren().add(path);
pathTransitionEllipse = PathTransitionBuilder.create()
.duration(Duration.seconds(4))
.path(path)
.node(rect)
.orientation(OrientationType.NONE)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(false)
.build();
rect.setLayoutX(rect.getLayoutX() + rect.getLayoutBounds().getWidth() / 2);
rect.setLayoutY(rect.getLayoutY() + rect.getLayoutBounds().getHeight() / 2);
// Circle path example
Rectangle rect2 = new Rectangle(0, 0, 20, 20);
rect2.setArcHeight(10);
rect2.setArcWidth(10);
rect2.setFill(Color.GREEN);
root.getChildren().add(rect2);
Path path2 = createEllipsePath(400, 200, 150, 150, 0);
root.getChildren().add(path2);
pathTransitionCircle = PathTransitionBuilder.create()
.duration(Duration.seconds(2))
.path(path2)
.node(rect2)
.orientation(OrientationType.NONE)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(false)
.build();
rect2.setLayoutX(rect2.getLayoutX() + rect2.getLayoutBounds().getWidth() / 2);
rect2.setLayoutY(rect2.getLayoutY() + rect2.getLayoutBounds().getHeight() / 2);
}
private Path createEllipsePath(double centerX, double centerY, double radiusX, double radiusY, double rotate) {
ArcTo arcTo = new ArcTo();
arcTo.setX(centerX - radiusX + 1); // to simulate a full 360 degree celcius circle.
arcTo.setY(centerY - radiusY);
arcTo.setSweepFlag(false);
arcTo.setLargeArcFlag(true);
arcTo.setRadiusX(radiusX);
arcTo.setRadiusY(radiusY);
arcTo.setXAxisRotation(rotate);
Path path = PathBuilder.create()
.elements(
new MoveTo(centerX - radiusX, centerY - radiusY),
arcTo,
new ClosePath()) // close 1 px gap.
.build();
path.setStroke(Color.DODGERBLUE);
path.getStrokeDashArray().setAll(5d, 5d);
return path;
}
@Override
public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
pathTransitionEllipse.play();
pathTransitionCircle.play();
}
public static void main(String[] args) {
launch(args);
}
}
实施说明
- 代码假定动画节点的原始布局位置为 0,0(如果不是,则需要相应调整)。
- 对于非方形节点,节点和路径之间存在微小间隙(因为计算是基于布局边界矩形而不是节点的可见形状)。
- 此外,路径转换使用的方向是,
NONE
而不是ORTHOGONAL_TO_TANGENT
(否则布局计算会在节点开始旋转时产生奇怪的效果,并且似乎节点正在向路径发散)。
除了上述方法,您可以定义一个自定义的Transition子类,它修改节点的TranslateX
和TranslateY
属性,以便节点的角跟随路径而不是中心,并且不需要修改节点的布局,但是那将是显着更多的工作。
于 2013-04-01T23:35:26.027 回答