Масштабируемая панель прокрутки в JavaFX - PullRequest
2 голосов
/ 14 октября 2019

Я пытаюсь реализовать прокручиваемую панель зума. Я начал с этого примера: JavaFx 8 - масштабирование / масштабирование ScrollPane относительно положения мыши . Однако у меня есть одна проблема - ширина линий и других объектов также увеличена, в то время как я хотел бы добиться эффекта безразмерности объектов. Поэтому я улучшил решение с помощью PointScalers здесь: JavaFX Как масштабировать координаты пути без изменения ширины линии? и мне удалось получить следующий результат: .

Это выглядит нормально, но сцена не масштабируется таким образом, чтобы точка, где я щелкаю, оставалась на месте во время преобразования. Вот мой код:

import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;

import java.util.List;

public class ZoomableScrollPane extends ScrollPane {

    private final List<PointScaler> scalers;
    private final Node targetNode, outerNode;

    private final double zoomIntensity = 0.1;
    private double scaleValue = 1.0;

    public ZoomableScrollPane(SignFeaturesPresenter signGroupPresenter) {
        super();
        this.scalers = signGroupPresenter.getScalers();
        this.targetNode = signGroupPresenter.getFeaturesGroup();
        this.outerNode = outerNode(this.targetNode);
        setContent(this.outerNode);
        setPannable(true);
    }

    private Node outerNode(Node node) {
        Node outerNode = centeredNode(node);
        outerNode.setOnScroll(e -> {
            e.consume();
            onScroll(e.getTextDeltaY(), new Point2D(e.getX(), e.getY()));
        });
        return outerNode;
    }

    private Node centeredNode(Node node) {
        VBox vBox = new VBox(node);
        vBox.setAlignment(Pos.CENTER);
        return vBox;
    }

    private void onScroll(double wheelDelta, Point2D mousePoint) {

        Bounds outerBounds = outerNode.getLayoutBounds();

        double zoomFactor = Math.exp(wheelDelta * zoomIntensity);
        scaleValue = scaleValue * zoomFactor;

        for (PointScaler scaler : scalers) {
            scaler.setScale(scaleValue);
        }

        this.layout();
        double newHvalue = mousePoint.getX()/outerBounds.getWidth();
        double newVvalue = mousePoint.getY()/outerBounds.getHeight();
        this.setHvalue(newHvalue);
        this.setVvalue(newVvalue);
    }

}

Я понимаю, почему уравнения для newHvalue и newVvalue не верны, но я не знаю, как их исправить. Я полагаю, что я должен использовать положение мыши в системе координат области просмотра, но я вижу, что позиция мыши находится в системе координат outerNode, которая многократно расширяет область просмотра. Кроме того, я не понимаю, что означает отрицательные значения для границ minX, minY, maxX, maxY, возвращаемых методом:

Bounds viewportBounds = getViewportBounds();

Например:

BoundingBox [minX:-3231.0, minY:-130.0, minZ:0.0, width:585.0, height:538.0, depth:0.0, maxX:-2646.0, maxY:408.0, maxZ:0.0]
...