如何修复JavaFX加载动画中途突然重置的问题
JavaFX加载动画中途重置问题修复
问题根源
- 动画进度计算错误:原代码中每个点的动画时长被错误设置为整个动画周期
animationDuration,导致第三个点在动画阶段结束时仍未完成完整的上下运动,就被强制重置到初始位置,视觉上表现为中途中断。 - 时间源不一致:使用
System.nanoTime()而非AnimationTimer提供的now参数计算时间,可能导致时间计算出现微小偏差,加剧动画异常。
修复方案
- 调整每个点的动画时长为总动画周期的1/3,确保三个点依次完成完整的运动周期后再进入暂停阶段。
- 统一使用AnimationTimer的
now参数作为时间基准,保证时间计算的准确性。
修复后的完整代码
package com.example.messengerappfx.util; import javafx.animation.AnimationTimer; import javafx.scene.layout.HBox; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; public class LoadingAnimation { private final HBox container = new HBox(5); private final Circle[] dots = new Circle[3]; private AnimationTimer timer; private long animationDuration; private long pauseDuration; private double amplitude = 10; private long startTime; public LoadingAnimation(long animationDuration, long pauseDuration) { this.animationDuration = animationDuration; this.pauseDuration = pauseDuration; initializeDots(); createAnimationTimer(); } private void initializeDots() { for (int i = 0; i < dots.length; i++) { Circle dot = new Circle(4, Color.LIGHTGRAY); dots[i] = dot; container.getChildren().add(dot); } } private void createAnimationTimer() { timer = new AnimationTimer() { @Override public void handle(long now) { if (startTime == 0) startTime = now; long elapsed = (now - startTime) / 1_000_000; long totalCycleDuration = animationDuration + pauseDuration; long currentCycleTime = elapsed % totalCycleDuration; animateDots(currentCycleTime); } }; } private void animateDots(long currentCycleTime) { if (currentCycleTime < animationDuration) { double dotAnimationDuration = animationDuration / 3.0; for (int i = 0; i < dots.length; i++) { double delay = i * dotAnimationDuration; double phase = Math.max(0, Math.min(1, (currentCycleTime - delay) / dotAnimationDuration)); dots[i].setTranslateY(-amplitude * Math.sin(phase * Math.PI)); } } else { resetDots(); } } private void resetDots() { for (Circle dot : dots) { dot.setTranslateY(0); } } public void start() { startTime = 0; timer.start(); } public void stop() { timer.stop(); } public HBox getNode() { return container; } }
说明
修复后,三个加载点会依次完成「向上移动到最高点→回到原位」的完整动画,整个动画阶段结束后所有点都回到初始位置,再进入暂停阶段,不会出现中途重置的异常。
内容的提问来源于stack exchange,提问作者Tim Weiss
相关产品推荐
相关产品推荐

