animation - JavaFX:基于时间函数的动画
问题描述
我没有 MWE,因为我不知道如何开始。我想我的问题主要是关于哪些是最适合这项工作的工具。
我有一个相当于 a 的对象Function<Double, VectorXYZ>
,它输出给定时间的对象的位置。它处理自己的插值。我想知道是否有一种方法可以处理 a 的功能Timeline
而不必使用KeyFrame
s。我希望既能向前播放,又能使用Slider
.
我想有一个DoubleProperty
以某种方式链接到的Timeline
,与更新包含对象Listener
的翻译属性的a 相关联。Group
但我不知道该怎么做。
谢谢你的帮助!
解决方案
所以是的,这是一个非常模糊的问题,但正如@James_D 所说,AnimationTimer
这是我正在寻找的工具。基本上我正在寻找对动画循环的低级访问,这似乎就是它。这是沿着场景中的某些路径的对象的 MWE。它将系统时间与场景时间(存储为 DoubleProperty)分开,以便可以暂停和重新启动,也可以通过 Slider 设置时间。
import com.google.common.base.Function;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.control.Slider;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class AnimationTestApp extends Application {
private static final double durationSeconds = 5;
private static final double screenWidthMeters = 10;
private static final double screenHeightMeters = 10;
private static final double pixelsPerMeter = 50;
private static final double squareSizeMeters = 0.5;
private static final double screenWidthPixels = pixelsPerMeter * screenWidthMeters;
private static final double screenHeightPixels = pixelsPerMeter * screenHeightMeters;
private static final double squareSizePixels = pixelsPerMeter * squareSizeMeters;
private static final double originXPixels = screenWidthPixels/2;
private static final double originYPixels = screenHeightPixels/2;
private final Rectangle square = new Rectangle(squareSizePixels, squareSizePixels, Color.RED);
private long lastTime = -1;
private boolean isStopped = true;
private double t = 0;
private DoubleProperty timeProperty;
private DoubleProperty timeProperty() {
if (timeProperty == null) {
timeProperty = new SimpleDoubleProperty();
timeProperty.addListener((obs, ov, nv) -> {updateScene();});
}
return timeProperty;
}
@Override
public void start(Stage primaryStage) throws Exception {
final SubScene subscene = new SubScene(new Group(square), screenWidthPixels, screenHeightPixels);
Slider timeSlider = new Slider(0, 5, 1);
timeSlider.valueProperty().bindBidirectional(timeProperty());
VBox root = new VBox(timeSlider, subscene);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
AnimationTimer animationTimer = buildTimer();
handleKeyboard(scene, animationTimer);
}
private AnimationTimer buildTimer() {
AnimationTimer animationTimer = new AnimationTimer() {
@Override
public void handle(long now) {
double elapsedNS = now - lastTime;
double dt = elapsedNS * 1E-9;
if (timeProperty().get() + dt > durationSeconds) {
stop();
}
timeProperty().set(timeProperty().get() + dt);
updateScene();//timeProperty.get());
lastTime = now;
}
@Override
public void start() {
lastTime = System.nanoTime();
isStopped = false;
if (timeProperty().get() > durationSeconds) {
timeProperty().set(0);
}
super.start();
}
@Override
public void stop() {
isStopped = true;
super.stop();
}
};
return animationTimer;
}
private void updateScene() {
double t = timeProperty().get();
Point2D point = positionFunction().apply(t);
double xPixels = originXPixels + point.getX() * pixelsPerMeter;
double yPixels = originYPixels + point.getY() * pixelsPerMeter;
square.setTranslateX(xPixels);
square.setTranslateY(yPixels);
}
private Function<Double, Point2D> positionFunction() {
double radius = 3;
double period = 2;
return (t) -> new Point2D(radius * Math.sin(2*Math.PI*t/period), radius * Math.cos(2*Math.PI*t/period));
}
private void handleKeyboard(Scene scene, AnimationTimer timer) {
scene.setOnKeyPressed((ke) -> {
if (ke.getCode().equals(KeyCode.SPACE)) {
if (isStopped) {timer.start();}
else {timer.stop();}
}
});
}
}
推荐阅读
- r - 循环仅检查 R 中向量的最后一个值
- css - 在 CSS 中,我如何选择*不是*具有符合可识别模式的类的容器元素的后代的元素?
- angularjs - AngularJS - 如果多次使用,指令内部的控制器仅被调用为第一个 deiretive
- javascript - 如何将中间点字符放入 .join() 中?
- node.js - 来自加密模块的 publicEncrypt,带有 RSA_PKCS1_PADDING,可能返回 255 字节而不是 256
- eclipse-rcp - 如何自定义 e4 应用程序的默认 SaveHandler?
- php - php 值在数组的名称中
- php - 带有 bindparam 的 PHP MySQL SELECT 语句不起作用
- r - R:类字符的分数到十进制 - 其他方法不起作用
- android - StartActivity - ActionView 无法打开文档 - Xamarin