0

I have a problem with zooming using javaFX and zooming. The items are wrapped in a group which is then scaled by the ZoomUtil. One node is animated to show the weird effect resulting: The Rectangles should stay within their original place and not constantly move around the frame.

I have no idea what causes this behaviour and tried many different transform settings and such but were not successful.

public class Test extends Application {

    @Override
    public void start(Stage primaryStage) {

        List<Rectangle> rectangles = new ArrayList<>(5);

        Color color = new Color(random(), random(), random(), 1);

        Rectangle r = new Rectangle(200, 140,color);
        r.relocate(-500,-500);
        rectangles.add(r);

        r = new Rectangle(200,140,color);
        r.relocate(500, -500);
        rectangles.add(r);

        r = new Rectangle(200,140,color);
        r.relocate(500, 500);
        rectangles.add(r);

        r = new Rectangle(200,140,color);
        r.relocate(0, 0);
        rectangles.add(r);

        r = new Rectangle(200,140,color);
        r.relocate(-500, 500);
        rectangles.add(r);


        Timeline timeline = new Timeline();

        Node circle = r;

        timeline.getKeyFrames().addAll(
                new KeyFrame(Duration.seconds(10), // set start position at 0
                        new KeyValue(circle.translateXProperty(), random() * 8000),
                        new KeyValue(circle.translateYProperty(), random() * 6000)
                ),
                new KeyFrame(new Duration(80000), // set end position at 40s
                        new KeyValue(circle.translateXProperty(), random() * 8000),
                        new KeyValue(circle.translateYProperty(), random() * 6000)
                )
        );


        Group group    = new Group();
        group.setManaged(false);

        group.getChildren().addAll(rectangles);

        StackPane pane = new StackPane();
        pane.setPrefWidth(500);
        pane.setPrefHeight(500);

        Scene scene    = new Scene(pane);

        pane.getChildren().add(group);

        pane.setOnScroll(event -> ZoomUtil.zoom(group, event));

        primaryStage.setScene(scene);
        primaryStage.setWidth(500);
        primaryStage.setHeight(500);
        primaryStage.show();

        timeline.play();

    }
}

.

public class ZoomUtil {

    /** Allow to zoom/scale any node with pivot at scene (x,y) coordinates.
     *
     * @param node
     * @param x
     * @param y
     */
    public static void zoom(Node node, double factor, double x, double y) {
        double oldScale = node.getScaleX();
        double scale = oldScale * factor;
        if (scale < 0.05) scale = 0.05;
        if (scale > 50)  scale = 50;

        node.setScaleX(scale);
        node.setScaleY(scale);

        double  f = (scale / oldScale) - 1;

        /* Move view by translational difference */
        Bounds bounds = node.localToScene(node.getBoundsInLocal());

        double dx = (x - (bounds.getWidth() / 2  + bounds.getMinX()));
        double dy = (y - (bounds.getHeight() / 2 + bounds.getMinY()));

        node.setTranslateX(node.getTranslateX() - f * dx);
        node.setTranslateY(node.getTranslateY() - f * dy);
    }

    public static void zoom(Node node, ScrollEvent event) {
        zoom(node, Math.pow(1.002, event.getDeltaY()), event.getSceneX(), event.getSceneY());
    }

    public static void zoom(Node node, ZoomEvent event) {
        zoom(node, event.getZoomFactor(), event.getSceneX(), event.getSceneY());
     }
 }
James_D
  • 201,275
  • 16
  • 291
  • 322
Jack Shade
  • 491
  • 5
  • 13

0 Answers0