优化 ScrollUtils (#3432)

* 优化 ScrollUtils

* update
This commit is contained in:
Glavo
2025-03-18 13:31:47 +08:00
committed by GitHub
parent d9e3816b8e
commit 0912613cfc

View File

@@ -25,14 +25,11 @@ import javafx.animation.Animation.Status;
import javafx.animation.KeyFrame; import javafx.animation.KeyFrame;
import javafx.animation.Timeline; import javafx.animation.Timeline;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent; import javafx.scene.input.ScrollEvent;
import javafx.util.Duration; import javafx.util.Duration;
import org.jackhuang.hmcl.util.Holder;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
/** /**
* Utility class for ScrollPanes. * Utility class for ScrollPanes.
@@ -142,23 +139,23 @@ final class ScrollUtils {
smoothScroll(scrollPane, speed, trackPadAdjustment); smoothScroll(scrollPane, speed, trackPadAdjustment);
} }
private static final double[] FRICTIONS = {0.99, 0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.04, 0.01, 0.008, 0.008, 0.008, 0.008, 0.0006, 0.0005, 0.00003, 0.00001};
private static final Duration DURATION = Duration.millis(3);
private static void smoothScroll(ScrollPane scrollPane, double speed, double trackPadAdjustment) { private static void smoothScroll(ScrollPane scrollPane, double speed, double trackPadAdjustment) {
final double[] frictions = {0.99, 0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.04, 0.01, 0.008, 0.008, 0.008, 0.008, 0.0006, 0.0005, 0.00003, 0.00001}; final double[] derivatives = new double[FRICTIONS.length];
final double[] derivatives = new double[frictions.length];
AtomicReference<Double> atomicSpeed = new AtomicReference<>(speed);
Timeline timeline = new Timeline(); Timeline timeline = new Timeline();
AtomicReference<ScrollDirection> scrollDirection = new AtomicReference<>(); Holder<ScrollDirection> scrollDirectionHolder = new Holder<>();
final EventHandler<MouseEvent> mouseHandler = event -> timeline.stop(); final EventHandler<MouseEvent> mouseHandler = event -> timeline.stop();
final EventHandler<ScrollEvent> scrollHandler = event -> { final EventHandler<ScrollEvent> scrollHandler = event -> {
if (event.getEventType() == ScrollEvent.SCROLL) { if (event.getEventType() == ScrollEvent.SCROLL) {
scrollDirection.set(determineScrollDirection(event)); ScrollDirection scrollDirection = determineScrollDirection(event);
if (isTrackPad(event, scrollDirection.get())) { scrollDirectionHolder.value = scrollDirection;
atomicSpeed.set(speed / trackPadAdjustment);
} else { double currentSpeed = isTrackPad(event, scrollDirection) ? speed / trackPadAdjustment : speed;
atomicSpeed.set(speed);
} derivatives[0] += scrollDirection.intDirection * currentSpeed;
derivatives[0] += scrollDirection.get().intDirection * atomicSpeed.get();
if (timeline.getStatus() == Status.STOPPED) { if (timeline.getStatus() == Status.STOPPED) {
timeline.play(); timeline.play();
} }
@@ -180,28 +177,26 @@ final class ScrollUtils {
} }
}); });
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(3), event -> { timeline.getKeyFrames().add(new KeyFrame(DURATION, event -> {
for (int i = 0; i < derivatives.length; i++) { for (int i = 0; i < derivatives.length; i++) {
derivatives[i] *= frictions[i]; derivatives[i] *= FRICTIONS[i];
} }
for (int i = 1; i < derivatives.length; i++) { for (int i = 1; i < derivatives.length; i++) {
derivatives[i] += derivatives[i - 1]; derivatives[i] += derivatives[i - 1];
} }
double dy = derivatives[derivatives.length - 1]; double dy = derivatives[derivatives.length - 1];
Function<Bounds, Double> sizeFunction = (scrollDirection.get() == ScrollDirection.UP || scrollDirection.get() == ScrollDirection.DOWN) ? Bounds::getHeight : Bounds::getWidth; double size;
double size = sizeFunction.apply(scrollPane.getContent().getLayoutBounds()); switch (scrollDirectionHolder.value) {
double value;
switch (scrollDirection.get()) {
case LEFT: case LEFT:
case RIGHT: case RIGHT:
value = Math.min(Math.max(scrollPane.hvalueProperty().get() + dy / size, 0), 1); size = scrollPane.getContent().getLayoutBounds().getWidth();
scrollPane.hvalueProperty().set(value); scrollPane.setHvalue(Math.min(Math.max(scrollPane.getHvalue() + dy / size, 0), 1));
break; break;
case UP: case UP:
case DOWN: case DOWN:
value = Math.min(Math.max(scrollPane.vvalueProperty().get() + dy / size, 0), 1); size = scrollPane.getContent().getLayoutBounds().getHeight();
scrollPane.vvalueProperty().set(value); scrollPane.setVvalue(Math.min(Math.max(scrollPane.getVvalue() + dy / size, 0), 1));
break; break;
} }