问题描述
我是 JavaFX 的新手,在尝试处理动画时遇到了问题.我知道 class PathTransition
提供了通过 class Path
沿着任意曲线在两点之间移动节点的方法;但似乎所有与 PathTransition
相关的类,如 Path
和 MoveTo
和 CubicCurveTo
并包括它自己, 只能在 xy 平面上工作.如果我想在 yz 平面或 xz 平面中移动节点怎么办?我只是在互联网上找不到任何关于它的信息.任何建议将不胜感激.
如
import javafx.animation.Animation;导入 javafx.animation.Interpolator;导入 javafx.animation.KeyFrame;导入 javafx.animation.KeyValue;导入 javafx.animation.ParallelTransition;导入 javafx.animation.PathTransition;导入 javafx.animation.PathTransition.OrientationType;导入 javafx.animation.Timeline;导入 javafx.animation.Transition;导入 javafx.application.Application;导入 javafx.scene.Group;导入 javafx.scene.PerspectiveCamera;导入 javafx.scene.Scene;导入 javafx.scene.effect.Bloom;导入 javafx.scene.input.MouseEvent;导入 javafx.scene.input.ScrollEvent;导入 javafx.scene.paint.Color;导入 javafx.scene.paint.PhongMaterial;导入 javafx.scene.shape.Box;导入 javafx.scene.shape.Circle;导入 javafx.scene.shape.Polygon;导入 javafx.scene.shape.Shape;导入 javafx.scene.shape.StrokeLineCap;导入 javafx.scene.transform.Rotate;导入 javafx.stage.Stage;导入 javafx.util.Duration;/*** @see http://stackoverflow.com/a/37370840/230513*/公共类螺旋扩展应用程序{私有静态最终双大小 = 300;私有最终内容内容 = Content.create(SIZE);公共无效播放(){content.animation.play();}私有静态最终类内容{私有静态最终持续时间 DURATION = Duration.seconds(4);private static final Color COLOR = Color.AQUA;私有静态最终双 WIDTH = 3;私人最终组组=新组();私人最终旋转 rx = new Rotate(0, Rotate.X_AXIS);私人最终旋转 ry = new Rotate(0, Rotate.Y_AXIS);私人最终旋转 rz = new Rotate(0, Rotate.Z_AXIS);私人最终 Box xAxis;私人最终框 yAxis;私人最终盒 zAxis;私人最终形状圈;私人最终形状箭头;私人最终动画动画;私有静态内容创建(双倍大小){内容 c = 新内容(大小);c.group.getChildren().addAll(c.arrow, c.circle,c.xAxis, c.yAxis, c.zAxis);c.group.getTransforms().addAll(c.rz, c.ry, c.rx);c.group.setTranslateX(-size/2);c.group.setTranslateY(-size/2);c.group.setTranslateZ(大小/2);c.rx.setAngle(35);c.ry.setAngle(-45);返回 c;}私人内容(双倍大小){xAxis = createBox(大小,宽度,宽度);yAxis = createBox(WIDTH, size, WIDTH);zAxis = createBox(WIDTH, WIDTH, size);圆 = 创建圆(大小);箭头 = createShape();动画 = 新的 ParallelTransition(createTransition(圆圈,箭头),创建时间线(大小/2));}私人圈 createCircle(双倍大小){圆 c = 新圆(大小/4);c.setFill(颜色.透明);c.setStroke(COLOR);返回 c;}私人盒子 createBox(双 w,双 h,双 d){框 b = 新框 (w, h, d);b.setMaterial(new PhongMaterial(COLOR));返回 b;}私有形状 createShape() {Shape s = new Polygon(0, 0, -10, -10, 10, 0, -10, 10);s.setStrokeWidth(WIDTH);s.setStrokeLineCap(StrokeLineCap.ROUND);s.setStroke(颜色);s.setEffect(new Bloom());返回 s;}私有过渡 createTransition(形状路径,形状节点){PathTransition t = new PathTransition(DURATION, path, node);t.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);t.setCycleCount(Timeline.INDEFINITE);t.setInterpolator(Interpolator.LINEAR);返回 t;}私人时间线 createTimeline(双倍大小){时间线 t = 新时间线();t.setCycleCount(Timeline.INDEFINITE);t.setAutoReverse(true);KeyValue keyX = new KeyValue(group.translateXProperty(), size);KeyValue keyY = new KeyValue(group.translateYProperty(), size);KeyValue keyZ = new KeyValue(group.translateZProperty(), -size);KeyFrame keyFrame = new KeyFrame(DURATION.divide(2), keyX, keyY, keyZ);t.getKeyFrames().add(keyFrame);返回 t;}}@覆盖public void start(Stage primaryStage) 抛出异常 {primaryStage.setTitle("JavaFX 3D");场景场景 = 新场景(内容组,大小 * 2,大小 * 2,真);primaryStage.setScene(场景);场景.setFill(颜色.黑色);scene.setOnMouseMoved((final MouseEvent e) -> {content.rx.setAngle(e.getSceneY() * 360/scene.getHeight());content.ry.setAngle(e.getSceneX() * 360/scene.getWidth());});PerspectiveCamera 相机 = new PerspectiveCamera(true);camera.setFarClip(SIZE * 6);相机.setTranslateZ(-3 * SIZE);场景.setCamera(相机);scene.setOnScroll((final ScrollEvent e) -> {camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());});primaryStage.show();玩();}公共静态无效主(字符串 [] args){发射(参数);}}
在这个相关的
cube.setOnMouseMoved(new EventHandler() {@覆盖公共无效句柄(最终鼠标事件 e){动画 = 新时间线();animation.getKeyFrames().addAll(新的关键帧(新的持续时间(2000),新 KeyValue(cube.rx.angleProperty(), e.getY()),新 KeyValue(cube.ry.angleProperty(), -e.getX()),新的 KeyValue(cube.rz.angleProperty(), e.getY())));动画播放();}});…pathBackFaceTransition = new PathTransition();pathBackFaceTransition.setPath(rectangleBackFace);…pathFrontFaceTransition = new PathTransition();pathFrontFaceTransition.setPath(rectangleFrontFace);…公共无效播放(){pathBackFaceTransition.play();pathFrontFaceTransition.play();}
最后,您可以使用针对缩放和平移属性的 KeyValue
模拟沿 x、y 和 z 轴的运动.再次参考
//用工厂创建一个keyValue:将圆缩放2倍KeyValue keyValueX = new KeyValue(stack.scaleXProperty(), 2);KeyValue keyValueY = new KeyValue(stack.scaleYProperty(), 2);KeyValue keyTransX = new KeyValue(stack.translateXProperty(), 100);KeyValue keyTransY = new KeyValue(stack.translateYProperty(), 100);//创建一个keyFrame,keyValue在时间2s到达持续时间 = Duration.millis(2000);//可以在到达关键帧时添加特定动作EventHandleronFinished = new EventHandler() {@覆盖公共无效句柄(ActionEvent t){//重置计数器我 = 0;}};KeyFrame keyFrame = new KeyFrame(duration, onFinished,keyValueX, keyValueY, keyTransX, keyTransY);
I'm new to JavaFX, and I encountered a problem when trying to deal with animation.I know class PathTransition
provides methods to move a node between two points along an arbitrary curve by class Path
; but it seems that all the classes that are related to PathTransition
, like Path
and MoveTo
and CubicCurveTo
and including itself, can only work in the xy plane. What if I want to move a node in the yz plane or xz plane? I just can't find any information about it on the internet. Any advice would be appreciated.
As shown in Animation Basics, Animations
, you can compose multiple kinds of Transition
, including PathTransition
, in a SequentialTransition
or ParallelTransition
. The approach is especially convenient when the equation of motion can be expressed in parametric form. Motion along a helix, shown below, uses a ParallelTransition
to combine a PathTransition
along a Circle
with a Timeline
along a line.
animation = new ParallelTransition(
createTransition(circle, arrow),
createTimeline(size / 2));
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.Timeline;
import javafx.animation.Transition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.effect.Bloom;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Shape;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* @see http://stackoverflow.com/a/37370840/230513
*/
public class Helix extends Application {
private static final double SIZE = 300;
private final Content content = Content.create(SIZE);
public void play() {
content.animation.play();
}
private static final class Content {
private static final Duration DURATION = Duration.seconds(4);
private static final Color COLOR = Color.AQUA;
private static final double WIDTH = 3;
private final Group group = new Group();
private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
private final Box xAxis;
private final Box yAxis;
private final Box zAxis;
private final Shape circle;
private final Shape arrow;
private final Animation animation;
private static Content create(double size) {
Content c = new Content(size);
c.group.getChildren().addAll(c.arrow, c.circle,
c.xAxis, c.yAxis, c.zAxis);
c.group.getTransforms().addAll(c.rz, c.ry, c.rx);
c.group.setTranslateX(-size / 2);
c.group.setTranslateY(-size / 2);
c.group.setTranslateZ(size / 2);
c.rx.setAngle(35);
c.ry.setAngle(-45);
return c;
}
private Content(double size) {
xAxis = createBox(size, WIDTH, WIDTH);
yAxis = createBox(WIDTH, size, WIDTH);
zAxis = createBox(WIDTH, WIDTH, size);
circle = createCircle(size);
arrow = createShape();
animation = new ParallelTransition(
createTransition(circle, arrow),
createTimeline(size / 2));
}
private Circle createCircle(double size) {
Circle c = new Circle(size / 4);
c.setFill(Color.TRANSPARENT);
c.setStroke(COLOR);
return c;
}
private Box createBox(double w, double h, double d) {
Box b = new Box(w, h, d);
b.setMaterial(new PhongMaterial(COLOR));
return b;
}
private Shape createShape() {
Shape s = new Polygon(0, 0, -10, -10, 10, 0, -10, 10);
s.setStrokeWidth(WIDTH);
s.setStrokeLineCap(StrokeLineCap.ROUND);
s.setStroke(COLOR);
s.setEffect(new Bloom());
return s;
}
private Transition createTransition(Shape path, Shape node) {
PathTransition t = new PathTransition(DURATION, path, node);
t.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
t.setCycleCount(Timeline.INDEFINITE);
t.setInterpolator(Interpolator.LINEAR);
return t;
}
private Timeline createTimeline(double size) {
Timeline t = new Timeline();
t.setCycleCount(Timeline.INDEFINITE);
t.setAutoReverse(true);
KeyValue keyX = new KeyValue(group.translateXProperty(), size);
KeyValue keyY = new KeyValue(group.translateYProperty(), size);
KeyValue keyZ = new KeyValue(group.translateZProperty(), -size);
KeyFrame keyFrame = new KeyFrame(DURATION.divide(2), keyX, keyY, keyZ);
t.getKeyFrames().add(keyFrame);
return t;
}
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("JavaFX 3D");
Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
primaryStage.setScene(scene);
scene.setFill(Color.BLACK);
scene.setOnMouseMoved((final MouseEvent e) -> {
content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
});
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setFarClip(SIZE * 6);
camera.setTranslateZ(-3 * SIZE);
scene.setCamera(camera);
scene.setOnScroll((final ScrollEvent e) -> {
camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
});
primaryStage.show();
play();
}
public static void main(String[] args) {
launch(args);
}
}
In this related example, the yellow shapes follow a Timeline
animation comprised of rotations of the cube's orthogonal axes, while also following a PathTransition
along the edges of a cube's face.
cube.setOnMouseMoved(new EventHandler<MouseEvent>() {
@Override
public void handle(final MouseEvent e) {
animation = new Timeline();
animation.getKeyFrames().addAll(
new KeyFrame(new Duration(2000),
new KeyValue(cube.rx.angleProperty(), e.getY()),
new KeyValue(cube.ry.angleProperty(), -e.getX()),
new KeyValue(cube.rz.angleProperty(), e.getY())
));
animation.play();
}
});
…
pathBackFaceTransition = new PathTransition();
pathBackFaceTransition.setPath(rectangleBackFace);
…
pathFrontFaceTransition = new PathTransition();
pathFrontFaceTransition.setPath(rectangleFrontFace);
…
public void play() {
pathBackFaceTransition.play();
pathFrontFaceTransition.play();
}
Finally, you can simulate motion along the x, y and z axes by using a KeyValue
that targets the scale and translate properties. Referring again to Animation Basics, the following change to TimelineEvents
creates the illusion of a 3-D shape moving to and fro.
//create a keyValue with factory: scaling the circle 2times
KeyValue keyValueX = new KeyValue(stack.scaleXProperty(), 2);
KeyValue keyValueY = new KeyValue(stack.scaleYProperty(), 2);
KeyValue keyTransX = new KeyValue(stack.translateXProperty(), 100);
KeyValue keyTransY = new KeyValue(stack.translateYProperty(), 100);
//create a keyFrame, the keyValue is reached at time 2s
Duration duration = Duration.millis(2000);
//one can add a specific action when the keyframe is reached
EventHandler<ActionEvent> onFinished = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
//reset counter
i = 0;
}
};
KeyFrame keyFrame = new KeyFrame(duration, onFinished,
keyValueX, keyValueY, keyTransX, keyTransY);
这篇关于Javafx:如何制作带有 3D 路径的动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!