我想更改PathTransition上节点的大小,以此降低节点在路径上的位置(持续时间)。 请参阅:JavaFX 2 circle path for animation作为动画的示例。JavaFX 2动画:缩放节点依赖PathTransition持续时间
节点的大小应该增加,直到达到Path的“中间”然后缩小。我想知道没有EventHandler,但已经完成了一个动画。
我想更改PathTransition上节点的大小,以此降低节点在路径上的位置(持续时间)。 请参阅:JavaFX 2 circle path for animation作为动画的示例。JavaFX 2动画:缩放节点依赖PathTransition持续时间
节点的大小应该增加,直到达到Path的“中间”然后缩小。我想知道没有EventHandler,但已经完成了一个动画。
我在此答案中更新了Uluk的示例,添加了一个ParallelTransition,该节点沿着路径传播时对节点进行缩放。对于路径的前半部分,节点的大小会增加。一旦节点在路径的一半,它就会缩小,直到在圆的开始处达到它的原始大小。
当我高速运行(您需要运行它来看这个)时,动画确实有一种奇怪的向前运动模糊效果,我无法真正解释。
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 ArcToScalingDemo extends Application {
private PathTransition pathTransitionEllipse;
private ParallelTransition scalingCirclePathTransition;
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(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(false)
.build();
// 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);
PathTransition pathTransitionCircle = PathTransitionBuilder.create()
.duration(Duration.seconds(2))
.path(path2)
.node(rect2)
.orientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(false)
.build();
ScaleTransition scaleTransition = ScaleTransitionBuilder.create()
.duration(pathTransitionCircle.getDuration().divide(2))
.fromX(1)
.fromY(1)
.toX(3)
.toY(3)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(true)
.build();
scalingCirclePathTransition = ParallelTransitionBuilder.create()
.children(pathTransitionCircle, scaleTransition)
.node(rect2)
.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();
scalingCirclePathTransition.play();
}
public static void main(String[] args) {
launch(args);
}
}
节点对路径中的位置不一定是相同的在动画中已过去,因为节点可以不以恒定速度行进的时间的相对持续时间。此外,在此示例中,节点的相对比例可能与这些值中的任何一个不完全匹配。您可以为ScaleTransition定义一个自定义的Interpolator,让您根据当前路径位置或动画持续时间将比例映射到一个值,但这并不是真的必要,因为在视觉上,插值看起来没有问题。
下面是另一个带自定义内插器的示例,它将沿着路径按比例调整节点的比例,以使节点在路径的一半处达到最大比例。它依赖于对称的原始路径转换中的插值函数。该样本尚未经过完全正确的测试。除非绝对必要,否则我会推荐先前没有定制插补器的示例。
public class ArcToInterpolation Demo extends Application {
class HalfInterpolator extends Interpolator {
final Interpolator source;
HalfInterpolator(Interpolator source) {
this.source = source;
}
@Override protected double curve(double t) {
return t <= 0.5
? source.interpolate(0.0, 1.0, t) * 2
: source.interpolate(0.0, 1.0, 1 - t) * 2;
}
}
private ParallelTransition scalingCirclePathTransition;
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root, 600, 460));
// 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);
PathTransition pathTransitionCircle = PathTransitionBuilder.create()
.duration(Duration.seconds(10))
.interpolator(Interpolator.EASE_BOTH)
.path(path2)
.node(rect2)
.orientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(false)
.build();
ScaleTransition scaleTransition = ScaleTransitionBuilder.create()
.duration(pathTransitionCircle.getDuration())
.interpolator(new HalfInterpolator(pathTransitionCircle.getInterpolator()))
.fromX(1)
.fromY(1)
.toX(4)
.toY(4)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(false)
.build();
scalingCirclePathTransition = ParallelTransitionBuilder.create()
.children(pathTransitionCircle, scaleTransition)
.node(rect2)
.build();
}
private Path createEllipsePath(double centerX, double centerY, double radiusX, double radiusY, double rotate) {
... as in previous sample
}
@Override
public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
scalingCirclePathTransition.play();
}
public static void main(String[] args) {
launch(args);
}
}
看起来你应该使用
公众最终ReadOnlyObjectProperty currentTimeProperty
PathTransition类。您可以在此属性的值更改上添加侦听器,并在出现新值时,调用double d = newDuration.toMillis(),并确定路径的哪一部分已经消失,并在动画的全部时间内将d除。
但我不能添加一个侦听器到PathTransition。所以我必须自己实现一个属性更改的监听器,而不是更简单的方法? – chrise
我认为,最简单的方法将是这样的:。 pathTransition.currentTimeProperty()的addListener(新的ChangeListener
感谢您的解决方案(double-upvote)。我认为ParallelTransition更适合FX方式,尽管您的答案完全符合我的问题。 – chrise
感谢您回答我所有的JavaFX问题。如果你可以提供插入代码,也许我以后需要它。到目前为止,它看起来非常好。非常感谢。 – chrise
已更新的答案提供一些示例插值代码。 – jewelsea