All versions of this documentation
X

Hierarchical advanced

The selected node is used as top of the hierarchy: click to change it dynamically.
Click an edge to make its extremities the top of the layout.
Play with the parameters of the layout to tweak the final result:

Open in a new window.
          <!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <script src="../build/ogma.min.js"></script>
  <style>
    #graph-container {
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      position: absolute;
      margin: 0;
      overflow: hidden;
    }

    #ui {
      font-family: Helvetica, Arial, sans-serif;
    }

    h4 {
      margin: 15px 5px 5px 5px;
    }

    .toolbar {
      display: block;
      position: absolute;
      top: 20px;
      right: 20px;
      padding: 0 10px 10px;
      box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
      border-radius: 4px;
      background: #ffffff;
      color: #222222;
      font-weight: 300;
    }

    .toolbar .section {
      position: relative;
      display: block;
    }

    .toolbar .section h4 {
      display: block;
      font-weight: 300;
      border-bottom: 1px solid #ddd;
      color: #606060;
      font-size: 1rem;
    }

    .controls {
      margin-top: 15px;
      clear: both;
    }

    .controls select {
      width: 100%;
      clear: both;
    }
  </style>
</head>

<body>
  <div id="graph-container"></div>

  <div class="toolbar" id="ui">
    <div class="section">
      <h4>Layout parameters</h4>
      <div class="controls">
        <label for="vertical">Level Distance</label>
        <input type="range" id="vertical" name="levelDistance" min="25" max="100" value="50">
      </div>
      <div class="controls">
        <label for="horizontal">Node Distance</label>
        <input type="range" id="horizontal" name="nodeDistance" min="25" max="100" value="50">
      </div>
      <div class="controls">
        <label for="horizontal">Component Distance</label>
        <input type="range" id="component" name="componentDistance" min="1" max="100" value="25">
      </div>
      <div class="controls">
        <label>Change Direction:</label>
        <select name="directionMode" id="directionMode">
          <option value="TB">Top Down</option>
          <option value="BT">Bottom Up</option>
          <option value="LR">Left to Right</option>
          <option value="RL">Right to Left</option>
        </select>
      </div>
      <div class="controls">
        <label>Arrange Components:</label>
        <select name="arrangeMode" id="arrangeMode">
          <option value="fit">Fit</option>
          <option value="grid">Grid</option>
          <option value="singleLine">Single Line</option>
        </select>
      </div>
    </div>
  </div>

  <script>
    'use strict';
    var ogma = new Ogma({
      container: 'graph-container',
    });

    var defaultLayoutOptions = {
      direction: 'TB',           // Direction of the layout. Can be TB, BT, LR, or RL,
      // where T = top, B = bottom, L = left, and R = right.
      duration: 300,           // Duration of the animation
      nodeDistance: 50,       // Number of pixels that separate nodes horizontally in the layout.
      levelDistance: 50,       // Number of pixels between each layer in the layout.
      componentDistance: 50,       // Number of pixels between each component in the layout.
      arrangeComponents: 'fit'
    };

    ogma.generate.balancedTree({
      children: 2,
      height: 5
    }).then(function (graph) {

      // add some extra nodes to show multi-component packing
      var extraNodes = Array.from({ length: 25 }).map(function (_, i) {
        return { id: 1000 + i };
      });
      graph.nodes = graph.nodes.concat(extraNodes);

      return ogma.setGraph(graph);

    }).then(function () {
      ogma.getNode(0).setSelected(true);
      runWithUIParameters();

    });

    function runLayout(options) {
      // Run layout
      ogma.layouts.hierarchical(options)
        .then(function () {
          console.log('done');
          ogma.view.locateGraph({
            easing: 'linear',
            duration: 300
          });
        });
    }

    ogma.events.onClick(function (evt) {
      var target = evt.target;

      // If the user clicked a node set it as root,
      // otherwise pick the link ends and make them roots
      if (target) {
        if (target.isNode) {
          target.setSelected(true);
        } else {
          target.getExtremities().setSelected(true);
        }
      }

      runWithUIParameters();
    });

    // UI controls
    var horizontalDistanceInput = document.getElementById('horizontal');
    var verticalDistanceInput = document.getElementById('vertical');
    var directionSelectInput = document.getElementById('directionMode');
    var arrangeSelectInput = document.getElementById('arrangeMode');
    var componentDistanceInput = document.getElementById('component');

    horizontalDistanceInput.addEventListener('change', runWithUIParameters);
    verticalDistanceInput.addEventListener('change', runWithUIParameters);
    componentDistanceInput.addEventListener('change', runWithUIParameters);
    directionSelectInput.addEventListener('change', runWithUIParameters);
    arrangeSelectInput.addEventListener('change', runWithUIParameters);

    function runWithUIParameters() {
      // create fresh new options
      var newOptions = {};
      for (var prop in defaultLayoutOptions) {
        newOptions[prop] = defaultLayoutOptions[prop];
      }
      // pass the roots to the layout
      newOptions.roots = ogma.getSelectedNodes();
      // now add the chosen one
      newOptions.direction = directionSelectInput.value;
      newOptions.nodeDistance = + horizontalDistanceInput.value;
      newOptions.levelDistance = + verticalDistanceInput.value;
      newOptions.componentDistance = + componentDistanceInput.value;
      newOptions.arrangeComponents = arrangeSelectInput.value;
      runLayout(newOptions);
    }

  </script>
</body>

</html>