Zydar
Zydar

Reputation: 167

How to zoom a pdf to the mouse position in javafx 2

I have to zoom a pdf-file thats inside of a ScrollPane. The ScrollPane itself is inside of a StackPane.
In the beginning I scale my pdf to fit the width of my ScrollPane. As a result of that the pdf-height doesn't fit the ScrollPanes height.
I already managed to zoom, by changing my scaleFactor when using the mousewheel. Unfortunately I can't zoom into a specific point.
I guess I have to change the ScrollPanes values depending on the mouse coordinates, but I just can't find the correct calculation. Can somebody please help me?

For example I tried

scrollPane.setVvalue(e.getY() / scrollPane.getHeight())

With this line of code my view just jumps up or down, depending on whether I click on the upper bound or the lower bound of my viewport.
I also understand that it has to behave like that, but I can't figure it out what has to be added/changed.

I use Jpedal to display my pdf

Hope you understand what I am looking for. Tell me if you need more information.

Edit:

Here is a snipped of how I managed to drag.

    eventRegion.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
        dragStartX = e.getX();
        dragStartY = e.getY();
    });

    eventRegion.addEventFilter(MouseEvent.MOUSE_DRAGGED, e -> {                     
        double deltaX = dragStartX - e.getX();
        double deltaY = dragStartY - e.getY();

        scrollPane.setHvalue(Math.min(scrollPane.getHvalue() + deltaX / scrollPane.getWidth(), scrollPane.getHmax()));          
        scrollPane.setVvalue(Math.min(scrollPane.getVvalue() + deltaY / scrollPane.getHeight(), scrollPane.getVmax()));                 

        e.consume();
    });

I think zooming to the mouse position could be done in a similar way, by just setting the Hvalue and Vvalue.
Any ideas how I can calculate these values?

Upvotes: 1

Views: 597

Answers (2)

Alessandro Giusa
Alessandro Giusa

Reputation: 1768

just for all related questions about "zooming where the mouse is".

I had the same problem and I came up with the following code snippet.

public void setZoom(final double x, final double y, final double factor) {
    // save the point before scaling
    final Point2D sceneToLocalPointBefore = this.sceneToLocal(x, y);

    // do scale
    this.setScaleX(factor);
    this.setScaleY(factor);

    // save the point after scaling
    final Point2D sceneToLocalPointAfter = this.sceneToLocal(x, y);

    // calculate the difference of before and after the scale
    final Point2D diffMousePoint = sceneToLocalPointBefore.subtract(sceneToLocalPointAfter);

    // translate the pane in order to point where the mouse is 
    this.setTranslateX(this.getTranslateX() - diffMousePoint.getX() * this.getScaleX());
    this.setTranslateY(this.getTranslateY() - diffMousePoint.getY() * this.getScaleY());
}

The basic idea is to move the underlying Pane to that point where it was before scaling. Important is the fact, that we calculate the mouse position to the local coordinate system of the Pane. After scale we do this just another time and calculate the difference. Once we know the difference we are able to move back the Pane. I think this solution is very easy and straightforward.

My setup in JavaFX is following: I have a javafx.scene.layout.BorderPane as root for my javafx.scene.Scene. In the center I put a Pane. This will be the Pane where I act on (i.e. put other Nodes in..zoom, move..etc.) If anyone is interested in how I actually did it, just mail me.

Good programming!

Upvotes: 1

RonSiven
RonSiven

Reputation: 959

This example has JavaFX 8 code for a zoomable, pannable ScrollPane with zoom to mouse pointer, reset zoom and fit to width of a rectangle which can really be any Node. Be sure to check out the answer to the question to get fitWidth() to work correctly. I am using this solution for an ImageView now, and it is slick.

Upvotes: 1

Related Questions