Skip to Main Content

How does one get infinite zoom out to work?

3015200Mar 24 2016 — edited Mar 24 2016

How does one get infinite zoom out to work?

To keep the explanation of the problem as simple as possible I have created a ScrollPane with this simple FXML.

   

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.Group?>

<?import javafx.scene.control.ScrollPane?>

<?import javafx.scene.layout.AnchorPane?>

<?import javafx.scene.layout.StackPane?>

<?import javafx.scene.shape.Circle?>

<?import javafx.scene.shape.Rectangle?>

<ScrollPane fx:id="topScrollPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: rgb(0,0,0);" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SimulationSelectionController">

   <content>

      <AnchorPane onScroll="#handleScroll">

         <children>

            <Rectangle fx:id="mouseEventSafetyNetRectangle" arcHeight="5.0" arcWidth="5.0" fill="#0000003c" height="700.0" stroke="BLACK" strokeType="INSIDE" width="700.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="5.0" />

            <Group fx:id="topScrollPaneGroup" onScroll="#handleScroll">

               <children>

                  <StackPane fx:id="topStackPane" layoutX="0" layoutY="0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity">

                     <children>

                        <Group fx:id="topStackPaneGroup" onScroll="#handleScroll">

                           <children>

<Circle fill="DODGERBLUE" layoutX="-98.0" layoutY="-127.0" radius="350.0" stroke="BLACK" strokeType="INSIDE" />

                           </children>

                        </Group>

                     </children>

                  </StackPane>

               </children>

            </Group>

         </children>

      </AnchorPane>

   </content>

</ScrollPane>

With this controller

package application;

import java.util.EventObject;

import javafx.fxml.FXML;

import javafx.geometry.Point2D;

import javafx.scene.Group;

import javafx.scene.Node;

import javafx.scene.control.ScrollPane;

import javafx.scene.input.ScrollEvent;

import javafx.scene.layout.StackPane;

import javafx.scene.shape.Box;

import javafx.scene.shape.Rectangle;

public class SimulationSelectionController {

      

      

    @FXML

       public Rectangle mouseEventSafetyNetRectangle;

       final double SCALE_DELTA = 1.1;

    @FXML

       public ScrollPane topScrollPane;

    @FXML

       public Group topScrollPaneGroup;

    @FXML

       public StackPane topStackPane;

    @FXML

       public Group topStackPaneGroup;

      

       protected void addMouseEventSafetyNetRectangle(ScrollPane sp) {

              System.out.println("Entered addMouseEventSafetyNetRectangle()");

             

              // double maxX = getDataModel().getBoundsInParent().getMaxX();

              // double minX = getDataModel().getBoundsInParent().getMinX();

              // double maxY = getDataModel().getBoundsInParent().getMaxY();

              // double minY = getDataModel().getBoundsInParent().getMinY();

              double width = sp.getBoundsInParent().getWidth();

              double height = sp.getBoundsInParent().getHeight();

              getMouseEventSafetyNetRectangle().setWidth(width);

              getMouseEventSafetyNetRectangle().setHeight(height);

              getMouseEventSafetyNetRectangle().setLayoutX(0);

              getMouseEventSafetyNetRectangle().setLayoutY(0);

              // getMouseEventSafetyNetRectangle().setOpacity(0);

       }

      

       private Point2D figureScrollOffset(Node scrollContent, ScrollPane scroller) {

           double extraWidth = scrollContent.getLayoutBounds().getWidth() - scroller.getViewportBounds().getWidth();

           // System.out.println("figureScrollOffset() extraWidth returned " + extraWidth);

           double sHvalue = scroller.getHvalue();

           double sHmin = scroller.getHmin();

           double sHMax = scroller.getHmax();

           double hScrollProportion = (scroller.getHvalue() - scroller.getHmin()) / (scroller.getHmax() - scroller.getHmin());

           // System.out.println("sHvalue returned " + sHvalue);

           // System.out.println("sHmin returned " + sHmin);

           // System.out.println("sHMax returned " + sHMax);

           // System.out.println("figureScrollOffset() hScrollProportion returned " + hScrollProportion);

           double scrollXOffset = hScrollProportion * Math.max(0, extraWidth);

           // System.out.println("figureScrollOffset() scrollXOffset returned " + scrollXOffset);

           double extraHeight = scrollContent.getLayoutBounds().getHeight() - scroller.getViewportBounds().getHeight();

           // System.out.println("figureScrollOffset() extraHeight returned " + extraHeight);

           double vScrollProportion = (scroller.getVvalue() - scroller.getVmin()) / (scroller.getVmax() - scroller.getVmin());

           // System.out.println("figureScrollOffset() vScrollProportion returned " + vScrollProportion);

           double scrollYOffset = vScrollProportion * Math.max(0, extraHeight);

           // System.out.println("figureScrollOffset() scrollYOffset returned " + scrollYOffset);

           // System.out.println("figureScrollOffset() returned " + scrollXOffset + " for X");

           // System.out.println("figureScrollOffset() returned " + scrollYOffset + " for Y");

           return new Point2D(scrollXOffset, scrollYOffset);

         }

      

        

         private Rectangle getMouseEventSafetyNetRectangle() {

              return mouseEventSafetyNetRectangle;

       }

         private double getSCALE_DELTA() {

              return SCALE_DELTA;

       }

              private ScrollPane getTopScrollPane() {

                     return topScrollPane;

              }

              private Group getTopScrollPaneGroup() {

                     return topScrollPaneGroup;

              }

              private StackPane getTopStackPane() {

                     return topStackPane;

              }

              private Group getTopStackPaneGroup() {

                     return topStackPaneGroup;

              }

              @FXML

              public void handleScroll(ScrollEvent se) {

                     double scrollDelta = 0;

                     double scaleFactor = 0;

                     Object wwEventObject = null;

                     System.out.println("Entered handleScroll()");

                     System.out.println("Event object fx:id is:" + se.getSource().getClass().getName() );

                    

                     se.consume();

                     wwEventObject = se.getSource();

                    

                     // System.out.println("event Source FX:id is: " + wwEventObject.getId());

                     // System.out.println("Mouse scroll wheel used.");

                     scrollDelta = se.getDeltaY();

                     // System.out.println("Mouse scroll wheel getDeltaY() is:" + scrollDelta);

                    

                     if (scrollDelta == 0) {

                        return;

                      }

                      scaleFactor = (se.getDeltaY() > 0) ? SCALE_DELTA

                          : 1 / SCALE_DELTA;

                      // amount of scrolling in each direction in scrollContent coordinate

                      // units

                      Point2D scrollOffset = figureScrollOffset(topScrollPaneGroup, topScrollPane);

                     

                     

                      ((Node)wwEventObject).setScaleX(((Node)wwEventObject).getScaleX() * scaleFactor);

                      ((Node)wwEventObject).setScaleY(((Node)wwEventObject).getScaleY() * scaleFactor);

                           addMouseEventSafetyNetRectangle(getTopScrollPane());

                     

                      // move viewport so that old center remains in the center after the

                      // scaling

                      repositionScroller(topScrollPaneGroup, topScrollPane, scaleFactor, scrollOffset);

              }

              @FXML

              protected void initialize() {

                     System.out.println("In initialize() method");

                     addMouseEventSafetyNetRectangle(getTopScrollPane());

                    

              }

              private void repositionScroller(Node scrollContent, ScrollPane scroller, double scaleFactor, Point2D scrollOffset) {

                         // System.out.println("In repositionScroller event method:");

                         double scrollXOffset = scrollOffset.getX();

                         double scrollYOffset = scrollOffset.getY();

                         double extraWidth = scrollContent.getLayoutBounds().getWidth() - scroller.getViewportBounds().getWidth();

                         if (extraWidth > 0) {

                           double halfWidth = scroller.getViewportBounds().getWidth() / 2 ;

                           double newScrollXOffset = (scaleFactor - 1) *  halfWidth + scaleFactor * scrollXOffset;

                           scroller.setHvalue(scroller.getHmin() + newScrollXOffset * (scroller.getHmax() - scroller.getHmin()) / extraWidth);

                         } else {

                           scroller.setHvalue(scroller.getHmin());

                         }

                         double extraHeight = scrollContent.getLayoutBounds().getHeight() - scroller.getViewportBounds().getHeight();

                         if (extraHeight > 0) {

                           double halfHeight = scroller.getViewportBounds().getHeight() / 2 ;

                           double newScrollYOffset = (scaleFactor - 1) * halfHeight + scaleFactor * scrollYOffset;

                           scroller.setVvalue(scroller.getVmin() + newScrollYOffset * (scroller.getVmax() - scroller.getVmin()) / extraHeight);

                         } else {

                            scroller.setVvalue(scroller.getVmin());

                         }

                       }

              private void setMouseEventSafetyNetRectangle(Rectangle mouseEventSaftyNetRectangle) {

                     this.mouseEventSafetyNetRectangle = mouseEventSaftyNetRectangle;

              }

Comments
Post Details
Added on Mar 24 2016
1 comment
543 views