我是 JavaFX 新手,在尝试处理动画时遇到了问题。我知道类PathTransition提供了按类沿任意曲线在两点之间移动节点的方法Path;但似乎所有与 相关的类PathTransition,例如Path和MoveTo以及CubicCurveTo和 ,包括它本身,都只能在xy平面上工作。如果我想在yz平面或xz平面中移动节点怎么办?我只是在互联网上找不到任何有关它的信息。任何意见,将不胜感激。
如动画基础知识中所示,Animations您可以在 a或中组合多种Transition,包括、 。当运动方程可以用参数形式表示时,该方法尤其方便。沿螺旋线的运动(如下所示)使用 a将 a沿 a与 a沿直线组合。PathTransitionSequentialTransitionParallelTransitionParallelTransitionPathTransitionCircleTimeline
animation = new ParallelTransition(\n createTransition(circle, arrow),\n createTimeline(size / 2));\nRun Code Online (Sandbox Code Playgroud)\n\n\n\nimport javafx.animation.Animation;\nimport javafx.animation.Interpolator;\nimport javafx.animation.KeyFrame;\nimport javafx.animation.KeyValue;\nimport javafx.animation.ParallelTransition;\nimport javafx.animation.PathTransition;\nimport javafx.animation.PathTransition.OrientationType;\nimport javafx.animation.Timeline;\nimport javafx.animation.Transition;\nimport javafx.application.Application;\nimport javafx.scene.Group;\nimport javafx.scene.PerspectiveCamera;\nimport javafx.scene.Scene;\nimport javafx.scene.effect.Bloom;\nimport javafx.scene.input.MouseEvent;\nimport javafx.scene.input.ScrollEvent;\nimport javafx.scene.paint.Color;\nimport javafx.scene.paint.PhongMaterial;\nimport javafx.scene.shape.Box;\nimport javafx.scene.shape.Circle;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Shape;\nimport javafx.scene.shape.StrokeLineCap;\nimport javafx.scene.transform.Rotate;\nimport javafx.stage.Stage;\nimport javafx.util.Duration;\n\n/**\n * @see http://stackoverflow.com/a/37370840/230513\n */\npublic class Helix extends Application {\n\n private static final double SIZE = 300;\n private final Content content = Content.create(SIZE);\n\n public void play() {\n content.animation.play();\n }\n\n private static final class Content {\n\n private static final Duration DURATION = Duration.seconds(4);\n private static final Color COLOR = Color.AQUA;\n private static final double WIDTH = 3;\n private final Group group = new Group();\n private final Rotate rx = new Rotate(0, Rotate.X_AXIS);\n private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);\n private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);\n private final Box xAxis;\n private final Box yAxis;\n private final Box zAxis;\n private final Shape circle;\n private final Shape arrow;\n private final Animation animation;\n\n private static Content create(double size) {\n Content c = new Content(size);\n c.group.getChildren().addAll(c.arrow, c.circle,\n c.xAxis, c.yAxis, c.zAxis);\n c.group.getTransforms().addAll(c.rz, c.ry, c.rx);\n c.group.setTranslateX(-size / 2);\n c.group.setTranslateY(-size / 2);\n c.group.setTranslateZ(size / 2);\n c.rx.setAngle(35);\n c.ry.setAngle(-45);\n return c;\n }\n\n private Content(double size) {\n xAxis = createBox(size, WIDTH, WIDTH);\n yAxis = createBox(WIDTH, size, WIDTH);\n zAxis = createBox(WIDTH, WIDTH, size);\n circle = createCircle(size);\n arrow = createShape();\n animation = new ParallelTransition(\n createTransition(circle, arrow),\n createTimeline(size / 2));\n }\n\n private Circle createCircle(double size) {\n Circle c = new Circle(size / 4);\n c.setFill(Color.TRANSPARENT);\n c.setStroke(COLOR);\n return c;\n }\n\n private Box createBox(double w, double h, double d) {\n Box b = new Box(w, h, d);\n b.setMaterial(new PhongMaterial(COLOR));\n return b;\n }\n\n private Shape createShape() {\n Shape s = new Polygon(0, 0, -10, -10, 10, 0, -10, 10);\n s.setStrokeWidth(WIDTH);\n s.setStrokeLineCap(StrokeLineCap.ROUND);\n s.setStroke(COLOR);\n s.setEffect(new Bloom());\n return s;\n }\n\n private Transition createTransition(Shape path, Shape node) {\n PathTransition t = new PathTransition(DURATION, path, node);\n t.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);\n t.setCycleCount(Timeline.INDEFINITE);\n t.setInterpolator(Interpolator.LINEAR);\n return t;\n }\n\n private Timeline createTimeline(double size) {\n Timeline t = new Timeline();\n t.setCycleCount(Timeline.INDEFINITE);\n t.setAutoReverse(true);\n KeyValue keyX = new KeyValue(group.translateXProperty(), size);\n KeyValue keyY = new KeyValue(group.translateYProperty(), size);\n KeyValue keyZ = new KeyValue(group.translateZProperty(), -size);\n KeyFrame keyFrame = new KeyFrame(DURATION.divide(2), keyX, keyY, keyZ);\n t.getKeyFrames().add(keyFrame);\n return t;\n }\n }\n\n @Override\n public void start(Stage primaryStage) throws Exception {\n primaryStage.setTitle("JavaFX 3D");\n Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);\n primaryStage.setScene(scene);\n scene.setFill(Color.BLACK);\n scene.setOnMouseMoved((final MouseEvent e) -> {\n content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());\n content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());\n });\n PerspectiveCamera camera = new PerspectiveCamera(true);\n camera.setFarClip(SIZE * 6);\n camera.setTranslateZ(-3 * SIZE);\n scene.setCamera(camera);\n scene.setOnScroll((final ScrollEvent e) -> {\n camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());\n });\n primaryStage.show();\n play();\n }\n\n public static void main(String[] args) {\n launch(args);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n在此相关示例中,黄色形状遵循Timeline由立方体正交轴旋转组成的动画,同时也遵循PathTransition沿着立方体面的边缘的动画。
cube.setOnMouseMoved(new EventHandler<MouseEvent>() {\n @Override\n public void handle(final MouseEvent e) {\n animation = new Timeline();\n animation.getKeyFrames().addAll(\n new KeyFrame(new Duration(2000),\n new KeyValue(cube.rx.angleProperty(), e.getY()),\n new KeyValue(cube.ry.angleProperty(), -e.getX()),\n new KeyValue(cube.rz.angleProperty(), e.getY())\n ));\n animation.play();\n }\n});\n\xe2\x80\xa6\npathBackFaceTransition = new PathTransition();\npathBackFaceTransition.setPath(rectangleBackFace);\n\xe2\x80\xa6\npathFrontFaceTransition = new PathTransition();\npathFrontFaceTransition.setPath(rectangleFrontFace);\n\xe2\x80\xa6\npublic void play() {\n pathBackFaceTransition.play();\n pathFrontFaceTransition.play();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n最后,您可以使用针对缩放和平移属性的来模拟沿x、y和z轴的运动。KeyValue再次参考动画基础知识,以下更改可TimelineEvents创建 3-D 形状来回移动的幻觉。
//create a keyValue with factory: scaling the circle 2times\nKeyValue keyValueX = new KeyValue(stack.scaleXProperty(), 2);\nKeyValue keyValueY = new KeyValue(stack.scaleYProperty(), 2);\nKeyValue keyTransX = new KeyValue(stack.translateXProperty(), 100);\nKeyValue keyTransY = new KeyValue(stack.translateYProperty(), 100);\n\n//create a keyFrame, the keyValue is reached at time 2s\nDuration duration = Duration.millis(2000);\n//one can add a specific action when the keyframe is reached\nEventHandler<ActionEvent> onFinished = new EventHandler<ActionEvent>() {\n @Override\n public void handle(ActionEvent t) {\n //reset counter\n i = 0;\n }\n};\nKeyFrame keyFrame = new KeyFrame(duration, onFinished,\n keyValueX, keyValueY, keyTransX, keyTransY);\nRun Code Online (Sandbox Code Playgroud)\n