title: Expand and collapse using sigma.js
body: <h2>Goal</h2>
  <p>I am trying to implement expand and collapse in <a href="https://github.com/jacomyal/sigma.js" rel="nofollow noreferrer">sigma.js</a>. On right click of any node it's adding the new node and connects its edge, but it is placed in random position.</p>
  <p>I want to add nodes in free space and they should not collide nor overlap with other nodes. It should expand slowly with an animation, expanding in free space area like <a href="https://bl.ocks.org/mbostock/1093130" rel="nofollow noreferrer">this example</a>. <a href="https://github.com/jacomyal/sigma.js/issues/905" rel="nofollow noreferrer">Related</a>.</p>
  <h2>Code</h2>
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
      &lt;title&gt; Airlines Graph Render &lt;/title&gt;
      &lt;script src=&quot;../build/sigma.min.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;../src/renderers/canvas/sigma.canvas.edges.curvedArrow.js&quot;&gt;&lt;/script&gt;
  
      &lt;script src=&quot;../plugins/sigma.layout.forceAtlas2/worker.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;../plugins/sigma.layout.forceAtlas2/supervisor.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;../plugins/sigma.renderers.edgeLabels/settings.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;../plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.curve.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;../plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.def.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;../plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.curvedArrow.js&quot;&gt;&lt;/script&gt;
      &lt;style&gt;
          body,html{
              width: 100%;
              margin: 0px;
              padding: 0px;
              height: 100%
          }
          #graph-container {
            width:100%;
            height: 100%;
          }
    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
  
        &lt;div id=&quot;graph-container&quot;&gt;&lt;/div&gt;
  
      &lt;script &gt;
          
          var graph = {
                  &quot;nodes&quot;: [
                      {
                          &quot;city&quot;: &quot;Dallas&quot;,
                          &quot;area&quot;: 999,
                          &quot;code&quot;: 214,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;Austin&quot;,
                          &quot;area&quot;: 1180,
                          &quot;code&quot;: 512,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;New York&quot;,
                          &quot;area&quot;: 1214,
                          &quot;code&quot;: 646,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;Washington&quot;,
                          &quot;area&quot;: 176,
                          &quot;code&quot;: 564,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;Atlanta&quot;,
                          &quot;area&quot;: 342,
                          &quot;code&quot;: 518,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;Huston&quot;,
                          &quot;area&quot;: 1625,
                          &quot;code&quot;: 281,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;Chicago&quot;,
                          &quot;area&quot;: 606,
                          &quot;code&quot;: 312,
                          &quot;country&quot;: &quot;USA&quot;
                      },
                      {
                          &quot;city&quot;: &quot;London&quot;,
                          &quot;area&quot;: 909,
                          &quot;code&quot;: 312,
                          &quot;country&quot;: &quot;England&quot;
                      }
                  ],
                  &quot;edges&quot;: [
                      {
                          &quot;key&quot;: 1,
                          &quot;source&quot;: &quot;Dallas&quot;,
                          &quot;destination&quot;: &quot;Austin&quot;,
                          &quot;distance&quot;: 200,
                          &quot;airlines&quot;: &quot;British Airways&quot;,
                          &quot;fare&quot;: 220
                      },
                      {
                          &quot;key&quot;: 2,
                          &quot;source&quot;: &quot;Austin&quot;,
                          &quot;destination&quot;: &quot;Dallas&quot;,
                          &quot;distance&quot;: 200,
                          &quot;airlines&quot;: &quot;Lufthansa&quot;,
                          &quot;fare&quot;: 120
                      },
                      {
                          &quot;key&quot;: 3,
                          &quot;source&quot;: &quot;Washington&quot;,
                          &quot;destination&quot;: &quot;Dallas&quot;,
                          &quot;distance&quot;: 1300,
                          &quot;airlines&quot;: &quot;Lufthansa&quot;,
                          &quot;fare&quot;: 300
                      },
                      {
                          &quot;key&quot;: 4,
                          &quot;source&quot;: &quot;Atlanta&quot;,
                          &quot;destination&quot;: &quot;Washington&quot;,
                          &quot;distance&quot;: 600,
                          &quot;airlines&quot;: &quot;Lufthansa&quot;,
                          &quot;fare&quot;: 600
                      },
                      {
                          &quot;key&quot;: 5,
                          &quot;source&quot;: &quot;Washington&quot;,
                          &quot;destination&quot;: &quot;Atlanta&quot;,
                          &quot;distance&quot;: 600,
                          &quot;airlines&quot;: &quot;KLM&quot;,
                          &quot;fare&quot;: 400
                      },
                      {
                          &quot;key&quot;: 6,
                          &quot;source&quot;: &quot;New York&quot;,
                          &quot;destination&quot;: &quot;Atlanta&quot;,
                          &quot;distance&quot;: 300,
                          &quot;airlines&quot;: &quot;Qatar&quot;,
                          &quot;fare&quot;: 1300
                      },
                      {
                          &quot;key&quot;: 7,
                          &quot;source&quot;: &quot;Huston&quot;,
                          &quot;destination&quot;: &quot;Atlanta&quot;,
                          &quot;distance&quot;: 800,
                          &quot;airlines&quot;: &quot;Indigo&quot;,
                          &quot;fare&quot;: 400
                      },
                      {
                          &quot;key&quot;: 8,
                          &quot;source&quot;: &quot;Atlanta&quot;,
                          &quot;destination&quot;: &quot;Huston&quot;,
                          &quot;distance&quot;: 800,
                          &quot;airlines&quot;: &quot;Spicejet&quot;,
                          &quot;fare&quot;: 600
                      },
                      {
                          &quot;key&quot;: 9,
                          &quot;source&quot;: &quot;New York&quot;,
                          &quot;destination&quot;: &quot;Chicago&quot;,
                          &quot;distance&quot;: 1000,
                          &quot;airlines&quot;: &quot;Air China&quot;,
                          &quot;fare&quot;: 500
                      },
                      {
                          &quot;key&quot;: 10,
                          &quot;source&quot;: &quot;Chicago&quot;,
                          &quot;destination&quot;: &quot;New York&quot;,
                          &quot;distance&quot;: 1000,
                          &quot;airlines&quot;: &quot;Jet Airways&quot;,
                          &quot;fare&quot;: 200
                      },
                      {
                          &quot;key&quot;: 11,
                          &quot;source&quot;: &quot;Dallas&quot;,
                          &quot;destination&quot;: &quot;Chicago&quot;,
                          &quot;distance&quot;: 900,
                          &quot;airlines&quot;: &quot;Lufthansa&quot;,
                          &quot;fare&quot;: 1300
                      },
                      {
                          &quot;key&quot;: 12,
                          &quot;source&quot;: &quot;Austin&quot;,
                          &quot;destination&quot;: &quot;Huston&quot;,
                          &quot;distance&quot;: 160,
                          &quot;airlines&quot;: &quot;Lufthansa&quot;,
                          &quot;fare&quot;: 240
                      },
                      {
                          &quot;key&quot;: 13,
                          &quot;source&quot;: &quot;Dallas&quot;,
                          &quot;destination&quot;: &quot;New York&quot;,
                          &quot;distance&quot;: 780,
                          &quot;airlines&quot;: &quot;Lufthansa&quot;,
                          &quot;fare&quot;: 300
                      }
                  ]
              };
          var g = {
              nodes:[],
              edges:[]
          }
  
      // Generate a random graph:
          
              colors = [
                '#617db4',
                '#668f3c',
                '#c6583e',
                '#b956af'
              ];
           sigma.utils.pkg('sigma.canvas.nodes');
           sigma.canvas.nodes.border = function(node, context, settings) {
                var prefix = settings('prefix') || '';
  
                context.beginPath();
                context.arc(
                  node[prefix + 'x']+15,
                  node[prefix + 'y'],
                  node[prefix + 'size']-2,
                  0,
                  Math.PI * 2,
                  true
                );
                //context.fillStyle = &quot;orange&quot;;
                context.strokeStyle = node.color || settings('defaultNodeColor');
                //get the data from the group
                //var data = d3.select(this).data();
                context.stroke();
                //context.fill();
                context.font = &quot;10px Arial&quot;;
                context.fillStyle = &quot;black&quot;;
                context.strokeStyle = &quot;black&quot;;
                //write the text in the context
                context.fillText(10,node[prefix + 'x']+15+ 10,  node[prefix + 'size']-2-15);
  
                // Adding a border
                //context.lineWidth = node.borderWidth || 1;
                //context.strokeStyle = node.borderColor || '#fff';
                //context.stroke();
  
                context.fillStyle = node.color || settings('defaultNodeColor');
                context.beginPath();
                context.arc(
                  node[prefix + 'x'],
                  node[prefix + 'y'],
                  node[prefix + 'size'],
                  0,
                  Math.PI * 2,
                  true
                );
  
               context.closePath();
               context.fill();
  
              };
  
          for (var i = 0; i &lt; graph.nodes.length; i++)
            g.nodes.push({
              id: graph.nodes[i]['city'],
              label: graph.nodes[i]['city'],
              x: Math.random(),
              y: Math.random(),
              size: 8,
              color: colors[Math.floor(Math.random() * colors.length)]
            });
  
          for (var i = 0; i &lt; graph.edges.length; i++)
            g.edges.push({
              id: graph.edges[i]['key'],
              source: graph.edges[i]['source'],
              target: graph.edges[i]['destination'],
              size: 8,
              label:graph.edges[i]['airlines'],
              color: '#668e3e',
              type:'curvedArrow'
            });
  
          s = new sigma({
            graph: g,
            renderer: {
              container: document.getElementById('graph-container'),
              type: 'canvas'
            },
            settings: {
              edgeLabelSize: 'proportional',
              minNodeSize: 1,
              maxNodeSize: 10,
              minEdgeSize: 0.1,
              maxEdgeSize: 2,
              enableEdgeHovering: true,
              edgeHoverSizeRatio: 2,
              defaultNodeType: 'border',
              defaultNodeColor:&quot;#fff&quot;,
              mouseEnabled: true,
              touchEnabled: true
            }
          });
  
          //s.settings('autoRescale', false)
  
          s.startForceAtlas2({worker: true, barnesHutOptimize: false});
          s.stopForceAtlas2();
  
          s.bind('rightClickNode', function(e) {
                  
                console.log(e.type, e.data.node.label, e.data.captor);
                  var name = 'New City'+Math.random();
                  s.graph.addNode({
                  id: name,
                  label: 'baai',
                  x: Math.random(),
                  y: Math.random(),
                  size: 8,
                  color: colors[Math.floor(Math.random() * colors.length)]
                });
                s.graph.addEdge({
                  id: name +Math.random(),
                  source: e.data.node.id,
                  target: name,
                  size: 8,
                  label:'bit'+Math.random(),
                  color: '#668e3e',
                  type:'curvedArrow'
                });
                
                // Edge with Already existing one
                s.graph.addEdge({
                  id: name+Math.random(),
                  source: 'Huston',
                  target: name,
                  size: 8,
                  label:'New City'+Math.random(),
                  color: '#668e3e',
                  type:'curvedArrow'
                });           
              setTimeout(function(){
                  s.refresh();
              },1000) 
              
          });
          
      &lt;/script&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  <h2>Attempts</h2>
  <p>On click of node I place nodes around it in a circular way by continuously increasing radius. In <a href="https://jsfiddle.net/sumeetpri/fony4chu/" rel="nofollow noreferrer">JSFiddle</a> you can see this. First click went good but on next click, it's getting one circle inside another. How much radius should I put so that it does not look like that (as in screenshot)?</p>
  <p><a href="https://i.stack.imgur.com/B7kWS.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/B7kWS.jpg" alt="enter image description here" /></a></p>
  <p>On second click it positions relatively and becomes like this screenshot. But I want actual positioning instead of relative.</p>
  <p><a href="https://i.stack.imgur.com/MmJcM.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MmJcM.jpg" alt="enter image description here" /></a></p>