JavaFx 动画-笔记
一、简介
JavaFX 是一个用于构建富客户端应用程序的现代图形用户界面(GUI)工具包,在替代早期的 Swing 框架,提供更强大的功能和更现代化的开发体验。
JavaFx 程序的实现是基于窗口、场景图、节点实现的。
JavaFX 动画是通过随时间变化来改变场景图中一个或多个节点的属性来实现的。
二、过度动画
通过预定义的过渡类实现常见的动画效果。
2、1过度动画实现
1、问题:创建一个正方形,使用一张图片填充,在图片放大的过程中逐渐变量,然后慢慢消失。
public class JavaFxImage extends Application {@Overridepublic void start(Stage primaryStage) throws Exception {//创建根节点Pane pane=new Pane();//创建图形节点Image image1=new Image("file:E:\\JavaFx\\img\\1.jpg");ImageView imageView1 = new ImageView(image1);imageView1.setFitHeight(200);imageView1.setFitWidth(200);imageView1.setX(200);imageView1.setY(200);//创建缩放动画ScaleTransition scaleTransition = new ScaleTransition();scaleTransition.setDuration(Duration.millis(2000));//scaleTransition.setNode(imageView1);scaleTransition.setByY(1.5);scaleTransition.setByX(1.5);scaleTransition.setCycleCount(1);scaleTransition.setAutoReverse(false);//创建淡入淡出动画FadeTransition fadeTransition=new FadeTransition();fadeTransition.setDuration(Duration.millis(2000));//fadeTransition.setNode(imageView1);fadeTransition.setFromValue(0.1);fadeTransition.setToValue(1.0);fadeTransition.setCycleCount(1);//Timeline.INDEFINITEfadeTransition.setAutoReverse(true);//创建并行执行动画ParallelTransition parallelTransition = new ParallelTransition(imageView1,fadeTransition, scaleTransition );parallelTransition.play();pane.getChildren().addAll(imageView1);Scene scene = new Scene(pane, 600, 600);scene.setFill(Color.BLACK);primaryStage.setTitle("测试动画");primaryStage.setScene(scene);primaryStage.show();}
}
2、2 时间轴动画
- 问题:创建一个图片节点,设置图片节点初始状态为模糊度为0,大小为0,让后让图片逐渐清晰,然后放大。
public class JavaFxImage2 extends Application {@Overridepublic void start(Stage primaryStage) throws Exception {//创建根节点Pane pane=new Pane();//创建图形节点Image image1=new Image("file:E:\\JavaFx\\img\\1.jpg");ImageView imageView1 = new ImageView(image1);imageView1.setFitHeight(200);imageView1.setFitWidth(200);imageView1.setX(200);imageView1.setY(200);// 2. 初始状态:完全透明 + 缩小到 50%imageView1.setOpacity(0); // 透明度 0(完全透明)imageView1.setScaleX(0); // X轴缩放 50%imageView1.setScaleY(0); // Y轴缩放 50%// 3. 创建时间轴动画Timeline timeline = new Timeline(new KeyFrame(Duration.ZERO, // 起始关键帧(0秒)new KeyValue(imageView1.opacityProperty(), 0), // 透明度从0开始new KeyValue(imageView1.scaleXProperty(), 0.0), // X缩放从0.0开始new KeyValue(imageView1.scaleYProperty(), 0.0) // Y缩放从0.0开始),new KeyFrame(Duration.seconds(3), // 结束关键帧(3秒)new KeyValue(imageView1.opacityProperty(), 1), // 透明度渐变到1(完全显示)new KeyValue(imageView1.scaleXProperty(), 1.5), // X缩放到100%new KeyValue(imageView1.scaleYProperty(), 1.5) // Y缩放到100%),new KeyFrame(Duration.seconds(5), // 结束关键帧(5秒)new KeyValue(imageView1.opacityProperty(), 1), // 透明度渐变到1(完全显示)new KeyValue(imageView1.scaleXProperty(), 2), // X缩放到100%new KeyValue(imageView1.scaleYProperty(), 2) // Y缩放到100%));// 4. 设置动画循环和播放timeline.setCycleCount(1); // 播放1次(默认)timeline.play();pane.getChildren().addAll(imageView1);Scene scene = new Scene(pane, 600, 600);scene.setFill(Color.BLACK);primaryStage.setTitle("测试动画");primaryStage.setScene(scene);primaryStage.show();}
}
3、3 创建基于帧更新的动画
问题:创建一个图片节点,设置图片节点初始状态为模糊度为0,大小为0,让后让图片逐渐清晰,然后放大。
public class JavaFxImage2 extends Application {private static final double ANIMATION_DURATION = 2.0; // 动画持续时间(秒)private long startTime = -1; // 动画开始时间戳(纳秒)private boolean isAnimating = false; // 动画状态标记@Overridepublic void start(Stage primaryStage) throws Exception {//创建根节点Pane pane=new Pane();//创建图形节点Image image1=new Image("file:E:\\JavaFx\\img\\1.jpg");ImageView imageView1 = new ImageView(image1);imageView1.setFitHeight(200);imageView1.setFitWidth(200);imageView1.setX(200);imageView1.setY(200);// 2. 初始状态:完全透明 + 缩小到 50%imageView1.setOpacity(0); // 透明度 0(完全透明)imageView1.setScaleX(0); // X轴缩放 50%imageView1.setScaleY(0); // Y轴缩放 50%// 3. 创建 AnimationTimer 控制逐帧动画AnimationTimer timer = new AnimationTimer() {@Overridepublic void handle(long now) {if (startTime < 0) {startTime = now; // 记录动画开始时间}// 计算已用时间(秒)double elapsedSeconds = (now - startTime) / 1_000_000_000.0;if (elapsedSeconds >= ANIMATION_DURATION) {// 动画结束:强制设置最终状态并停止计时器imageView1.setOpacity(1);imageView1.setScaleX(1);imageView1.setScaleY(1);stop();isAnimating = false;return;}// 计算动画进度(0.0 → 1.0)double progress = elapsedSeconds / ANIMATION_DURATION;// 更新透明度和缩放属性imageView1.setOpacity(progress); // 线性淡入imageView1.setScaleX(0.5 + 0.5 * progress); // 从 0.5 放大到 1.0imageView1.setScaleY(0.5 + 0.5 * progress);}};// 4. 点击图片重新播放动画(可选交互)imageView1.setOnMouseClicked(e -> {if (!isAnimating) {// 重置初始状态imageView1.setOpacity(0);imageView1.setScaleX(0.5);imageView1.setScaleY(0.5);startTime = -1; // 重置时间戳isAnimating = true;timer.start();}});// 5. 首次自动启动动画isAnimating = true;timer.start();pane.getChildren().addAll(imageView1);Scene scene = new Scene(pane, 600, 600);scene.setFill(Color.BLACK);primaryStage.setTitle("测试动画");primaryStage.setScene(scene);primaryStage.show();}
}