1
1

I'm using the mxClient.js (version 1.10.1.4) to draw the mxGraph.

I enabled rubberband selection using: new $wnd.mxRubberband(graph);

Now I want to zoom the graph to show only selected nodes. I know that there is a mxGraph.prototype.zoomTo=function(a,b){this.zoom(a/this.view.scale,b)}; method.

How do I get the a and b parameters?

asked 17 Sep '12, 07:41

Tilak's gravatar image

Tilak
1113
accept rate: 0%

edited 29 Oct '12, 17:57

David's gravatar image

David
4.9k21831


The mxGraph 1.10.4.2 release has a mxGraph.zoomToRect() function added. This takes an mxRectangle as the parameter and scales and translates the display so that rectangle is just visible.

To implement a rubber band handler that zooms to the selection area, use:

mxRubberband.prototype.mouseUp = function(sender, me) {

   var execute = this.div != null;
   this.reset();

   if (execute)
   {
    var rect = new mxRectangle(this.x, this.y, this.width, this.height);
    var graph = this.graph;

    graph.zoomToRect(rect);
    me.consume();
  }
};

Note that the input rectangle is neither translated nor scaled and that it's screen co-ordinates that are passed in.

link

answered 29 Oct '12, 17:56

David's gravatar image

David
4.9k21831
accept rate: 47%

edited 15 Jan '13, 14:53

I extended my example from a previous post to support zooming to the rubberband rectangle. It's in Java though, but maybe you can get the drift for the Javascript version (which I don't have and hence can't help with).

Here's the code, the interesting part starts at "// add rubberband zoom":

package com.mxgraph.examples.swing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.mxGraphOutline;
import com.mxgraph.swing.handler.mxRubberband;
import com.mxgraph.view.mxGraph;

public class ZoomAndCenterExample_v2 {

    public ZoomAndCenterExample_v2() {

        JFrame frame = new JFrame();
        frame.setSize(500, 500);
        frame.setLocation(300, 200);

        final mxGraph graph = new mxGraph();

        Object parent = graph.getDefaultParent();
        graph.getModel().beginUpdate();
        try {
            Object v1 = graph.insertVertex(parent, null, "node1", 100, 100, 80, 30);
            Object v2 = graph.insertVertex(parent, null, "node2", 1000, 100, 80, 30);
            Object v3 = graph.insertVertex(parent, null, "node3", 100, 1000, 80, 30);

            graph.insertEdge(parent, null, "Edge", v1, v2);
            graph.insertEdge(parent, null, "Edge", v2, v3);

        } finally {
            graph.getModel().endUpdate();
        }

        final mxGraphComponent graphComponent = new mxGraphComponent(graph);
        frame.getContentPane().add(graphComponent, BorderLayout.CENTER);

        // create toolbar (graphOutline and toolbar Buttons
        JPanel toolBar = new JPanel();
        toolBar.setLayout(new BorderLayout());

        // graphOutline
        final mxGraphOutline graphOutline = new mxGraphOutline(graphComponent);
        graphOutline.setPreferredSize(new Dimension(100, 100));
        toolBar.add(graphOutline, BorderLayout.WEST);

        // toolbar Buttons
        JPanel buttonBar = new JPanel();
        buttonBar.setLayout(new FlowLayout());

        // zoom to fit
        JButton btZoomToFit = new JButton("Zoom To Fit ViewPort");
        btZoomToFit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

                double newScale = 1;

                Dimension graphSize = graphComponent.getGraphControl().getSize();
                Dimension viewPortSize = graphComponent.getViewport().getSize();

                int gw = (int) graphSize.getWidth();
                int gh = (int) graphSize.getHeight();

                if (gw > 0 && gh > 0) {
                    int w = (int) viewPortSize.getWidth();
                    int h = (int) viewPortSize.getHeight();

                    newScale = Math.min((double) w / gw, (double) h / gh);
                }

                graphComponent.zoom(newScale);

            }
        });
        buttonBar.add(btZoomToFit);

        // center graph
        JButton btCenter = new JButton("Center Graph in ViewPort");
        btCenter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

                Dimension graphSize = graphComponent.getGraphControl().getSize();
                Dimension viewPortSize = graphComponent.getViewport().getSize();

                int x = graphSize.width/2 - viewPortSize.width/2;
                int y = graphSize.height/2 - viewPortSize.height/2;
                int w = viewPortSize.width;
                int h = viewPortSize.height;

                graphComponent.getGraphControl().scrollRectToVisible( new Rectangle( x, y, w, h));

            }
        });
        buttonBar.add(btCenter);

        // add rubberband zoom
        new mxRubberband(graphComponent) {

            public void mouseReleased(MouseEvent e)
            {
                // get bounds before they are reset
                Rectangle rect = bounds;

                // invoke usual behaviour
                super.mouseReleased(e);

                if( rect != null) {

                    double newScale = 1;

                    Dimension graphSize = new Dimension( rect.width, rect.height);
                    Dimension viewPortSize = graphComponent.getViewport().getSize();

                    int gw = (int) graphSize.getWidth();
                    int gh = (int) graphSize.getHeight();

                    if (gw > 0 && gh > 0) {
                        int w = (int) viewPortSize.getWidth();
                        int h = (int) viewPortSize.getHeight();

                        newScale = Math.min((double) w / gw, (double) h / gh);
                    }

                    // zoom to fit selected area
                    graphComponent.zoom(newScale);

                    // make selected area visible 
                    graphComponent.getGraphControl().scrollRectToVisible( new Rectangle( (int) (rect.x * newScale), (int) (rect.y * newScale),  (int) (rect.width * newScale),  (int) (rect.height * newScale)));

                }

            }

        };

        // put components on frame
        toolBar.add(buttonBar, BorderLayout.CENTER);
        frame.getContentPane().add(toolBar, BorderLayout.SOUTH);
        frame.setVisible(true);

    }

    public static void main(String[] args) {
        ZoomAndCenterExample_v2 t = new ZoomAndCenterExample_v2();

    }

}

Here's me dragging a rubberband:

alt text

And this happens when I release the mouse:

alt text

In case you want the selected cells as a whole visible, of course you have to get the bounds of the selected cells with the existing functions first and then use that rectangle on the zoom factor calculation.

link

answered 27 Sep '12, 10:41

Lofi's gravatar image

Lofi
1.0k1221
accept rate: 37%

edited 27 Sep '12, 10:43

Thanks a lot for the useful example.

I did similar coding in JavaScript:

/start/ var view = graph.getView(); var boundsOfSelectedCells = view.getBounds(selectedCells); var x = boundsOfSelectedCells.getPoint().x; var y = boundsOfSelectedCells.getPoint().y; var width = boundsOfSelectedCells.width; var height = boundsOfSelectedCells.height;

var newScale = 1;

if (width > 0 && height > 0) { newScale = Math.min( containerWidth / width, containerHeight / height); }

graph.zoom(newScale);

graph.scrollRectToVisible(new $wnd.mxRectangle( xnewScale, ynewScale, widthnewScale, heightnewScale));

/end/

This zooms the graph a bit more and scrolls atleast 50 pixels to the right.

How to fix it?

(28 Sep '12, 09:14) Tilak

The correct function would be:

ZoomingRubberband.prototype.mouseUp = function(sender, me) {
    var execute = this.div != null;
    this.reset();

    if (execute) {
        var graph = this.graph;
        console.log(graph.getView().getScale());
        var rect = new mxRectangle(this.x / graph.getView().getScale(), this.y / graph.getView().getScale(), this.width / graph.getView().getScale(), this.height / graph.getView().getScale());

        graph.zoomToRect(rect);

    }
};

Otherwise the rubberband zoom is only correct for the first time as the aspect ratio is not taken into account!

link

answered 18 Jan '13, 06:43

Ltty's gravatar image

Ltty
629
accept rate: 25%

I've tested the accepted section of code extensively, I haven't found any problems with it.

(18 Jan '13, 06:49) David

The problem is that if you have already zoomed in once and you use the rubberband for another zoom it can be that the graph zooms out again instead of further in. Is is because the aspect ratio (scale) has to be included. Otherwise the zoom rectangle is always created for the whole container and not for the current zoom. If you zoom in to a node with the rubberband first and then try to zoom in a second time maybe showing only half of the node you will see what I mean.

(18 Jan '13, 10:22) Ltty

I tried again, my code I quoted works for me correctly on both the orgchart example and grapheditor on mutliple zoom selections using mxGraph 1.10.4.2. Can you show me an example of this failure?

(18 Jan '13, 12:32) David

Have a look at https://dl.dropbox.com/u/12647354/screenshot_04.png

In a) you see the result of your code, when you do not devide by the scale. If you perform the zoom a second time, the rubberband selection won't zoom in any further. Instead it can even happen that you zoom out again, if you select the whole rectangle again.

In b) you see continous zoom by taking the current scale into account.

All in all I'd say this is a minor and negligible glitch...

(21 Jan '13, 04:52) Ltty
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×228
×39
×13
×9
×1

Asked: 17 Sep '12, 07:41

Seen: 4,218 times

Last updated: 21 Jan '13, 04:52