2

I am trying to implement a scrollable zoom pane. I started from this example: JavaFx 8 - Scaling / zooming ScrollPane relative to mouse position. There is however one problem I have with this - the width of the lines and other objects is zoomed too, while I would like to achieve the effect that the features are dimensionless. Therefore I improved the solution with PointScalers from here: JavaFX How do I scale the coordinates of a Path without altering the line width? and managed to get the following result: .

This looks fine, but the scene is not zoomed in a way that the point where I click remains in place during the transformation. Here is my code:

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);
    }

}

I understand why the equations for newHvalue and newVvalue are not correct, but I do not know how to correct them. I suppose I should use the position of the mouse in the viewport coordinate system, but I can see that the mouse position is in the outerNode coordinate system, which extends the viewport many times. Also, I do not understand, what is the meaning of negative values for the minX, minY, maxX, maxY bounds returned by the method:

Bounds viewportBounds = getViewportBounds();

For example:

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]
Piotr G
  • 959
  • 1
  • 7
  • 25

0 Answers0