anvaka / VivaGraphJS

Graph drawing library for JavaScript
Other
3.73k stars 423 forks source link

How to size the graph to fit the maximum window size? #193

Open mj-fintech opened 7 years ago

mj-fintech commented 7 years ago

Hi,

I built a network graph using vivagraph, and forcelayout. Nodes are dispersing from (0,0) to outward and makes circular shape system. I have about 400 nodes and they are keep dispersing though at some point they are quite stabilized (but still moving).

What I want: I want the graph to fit into the available window size. Two ways I thought about.

  1. stopping the layout dispersion using layout.pause() method.
  2. scale the svg to the window size.
  3. use constant layout and positioning each node specifically.

Problems: for 1, I do not know how should I apply the layout.pause() when and where in my code. for 2, I tried scaling the svg using viewBox method, but it didn't work out. Didn't have any effect. for 3, it will take alot of time to define each and every node position for over 400 nodes.

Below is my code:

    ## data from Python Flask
    var linkdata = {{ linkdata|safe }}  
    var graph = Viva.Graph.graph();

    ## forceDirected layout
    var layout = Viva.Graph.Layout.forceDirected(graph, {
          springLength:20,
          springCoeff:0,
          dragCoeff:0.1,
          gravity: -0.0025,
          theta: 0.3
      });

    ## add links using the data
    for (i = 0; i<linkdata.length; i++) {    
            graph.addLink(linkdata[i]['source'],linkdata[i]['target']);
    };   

    ## other codes including graphincs.node(function...... and then
    .placeNode(function(nodeUI, pos){
            // Shift image to let links go to the center:
            nodeUI.attr('transform',
                        'translate('+ 
                                (pos.x - nodeSize) + ',' + (pos.y - nodeSize) + ')');
        });

        graphics.link(function(link){
            return Viva.Graph.svg('path')
                       .attr('stroke', 'transparent')
                       .attr('stroke-width', 0.5);

        }).placeLink(function(linkUI, fromPos, toPos) {
            var data = 'M' + fromPos.x + ',' + fromPos.y +
                       'L' + toPos.x + ',' + toPos.y;
            linkUI.attr("d", data);
        });

    var renderer = Viva.Graph.View.renderer(graph,
        {
            layout : layout,
            graphics : graphics
        });

    renderer.run();

Where should I and how should I define the layout.pause method? If I were to use svg scaling where and how should I apply the viewBox scaling?

I tried

and right at the "graphics" as an .attr('viewBox', '0 0 60 55'), but didn't work out.

Please let me know if you have some ideas to solve my problem. The svg got too big unless using scaling or layout.pause method, and it will be harder for users to see/browse the network.

anvaka commented 7 years ago

You can explore lastMove property of your layout from time to time (e.g. inside setTimeout() function). Depending on amount of nodes/edges in the graph this number should be decreasing, and you can decide when to stop.

Alternatively you can just count number of iterations (layout fires step event after each iteration) and decide that it's time to stop. This logic can be a function of number of nodes/edges.

khawarizmus commented 7 years ago

@anvaka is it possible to pin a node in this scenario in staid of stopping the renderer ?