6

如何在 JavaFX 2 中创建圆形(或椭圆) javafx.scene.shape.Path ?

我发现了一些使用 CubicCurveTo 的例子:

Path path = new Path();
path.getElements().add(new CubicCurveTo(30, 10, 380, 120, 200, 120));

但我不明白贝塞尔坐标。我需要一个完整的动画路径。

4

3 回答 3

10

您可以利用ArcTopath 元素来绘制圆形或椭圆形路径:

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.ORTHOGONAL_TO_TANGENT)
                .cycleCount(Timeline.INDEFINITE)
                .autoReverse(false)
                .build();


        // Cirle 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.ORTHOGONAL_TO_TANGENT)
                .cycleCount(Timeline.INDEFINITE)
                .autoReverse(false)
                .build();
    }

    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);
    }
}

ArcTo 功能的良好参考是ArcTo (JavaFX 8)。虽然是第 8 版,但功能的含义是相似的。
输出:
在此处输入图像描述

于 2013-01-05T14:36:49.560 回答
3

这是@Uluk Biy 答案的更新版本。

import javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcTo;
import javafx.scene.shape.ClosePath;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class PathTDemo 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 = new PathTransition();
        pathTransitionEllipse.setDuration(Duration.seconds(4));
        pathTransitionEllipse.setPath(path);
        pathTransitionEllipse.setNode(rect);
        pathTransitionEllipse.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
        pathTransitionEllipse.setCycleCount(Timeline.INDEFINITE);
        pathTransitionEllipse.setAutoReverse(false);

        // Cirle 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 = new PathTransition();
        pathTransitionCircle.setDuration(Duration.seconds(2));
        pathTransitionCircle.setPath(path2);
        pathTransitionCircle.setNode(rect2);
        pathTransitionCircle.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
        pathTransitionCircle.setCycleCount(Timeline.INDEFINITE);
        pathTransitionCircle.setAutoReverse(false);
    }

    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 = new Path();
        path.getElements().addAll(
                new MoveTo(centerX - radiusX, centerY - radiusY),
                arcTo,
                new ClosePath()); // close 1 px gap.
        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);
    }
}
于 2018-05-02T14:46:28.980 回答
0

我通过容器的rotateProperty 动画解决了同样的问题。只需两行即可创建动画。

    animationTimeLine = new Timeline(60, new KeyFrame(Duration.seconds(5), new KeyValue(circlePane.rotateProperty(), 360.0)));

    animationTimeLine.setCycleCount(INDEFINITE);
于 2015-04-29T08:04:00.580 回答