All versions of this documentation
X

Visual grouping of arctic web

ArcticWEB is an academic initiative to create an international network of scientists dedicated to conduct active multi-disciplinary research on ecosystem processes in the Arctic. See how Ogma allows you to group articles by topic while still showing the inner connections inside of the fields.

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

<head>
  <meta charset="utf-8">
  <script src="../build/ogma.min.js"></script>
  <style>
    body,
    html {
      font-family: Helvetica, Arial, sans-serif;
    }

    #graph-container {
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      position: absolute;
      margin: 0;
      overflow: hidden;
    }

    button {
      position: absolute;
      top: 10px;
      left: 10px;
    }

    #group-layout-btn {
      position: absolute;
      top: 40px;
    }

    #layout-btn {
      top: 70px;
    }

    #legend {
      display: block;
      position: absolute;
      bottom: 20px;
      left: 20px;
    }

    #legend ul {
      list-style: none;
    }

    #legend ul li .color {
      display: inline-block;
      width: 1em;
      height: 1em;
      margin-right: 5px;
    }
  </style>
</head>

<body>
  <div id="graph-container"></div>
  <button id="group-btn" onclick="toggleGroup()">Group articles by field</button>
  <button id="group-layout-btn" onclick="layoutGroup()" disabled>Layout selected group</button>
  <button id="layout-btn" onclick="layoutGraph()">Layout graph</button>
</body>
<script>
  var ogma = new Ogma({
    container: 'graph-container'
  });
  var names = {
    'rgba(51, 153, 255, 1)': 'Arctic, communities',
    'rgba(0, 204, 204, 1)': 'Research',
    'rgba(153, 255, 255, 1)': 'Population',
    'rgba(255, 204, 51, 1)': 'Aerospace',
    'rgba(255, 204, 102, 1)': 'Geosciences',
    'rgba(255, 255, 51, 1)': 'Physics',
    'rgba(102, 0, 102, 1)': 'Petrol',
    'rgba(153, 0, 0, 1)': 'Political Studies',
    'rgba(102, 102, 0, 1)': 'Pollution',
    'rgba(0, 153, 0, 1)': 'Energy resources',
    'rgba(153, 255, 0, 1)': 'Biodiversity',
    'rgba(0, 204, 51, 1)': 'Global warming',
  };

  function toggleButton(on) {
    var button = document.getElementById('group-btn');
    button.innerHTML = on ? 'Ungroup' : 'Group articles by field';
  }

  // toggle group layout button based on whether there are selected groups
  function onSelectionChange(evt) {
    var nodes = evt.nodes;
    var metaNodes = nodes.filter(function (node) {
      return node.getSubNodes() !== null;
    });
    var button = document.getElementById('group-layout-btn');
    if (metaNodes.isSelected().some(function (selected) { return selected })) {
      button.removeAttribute('disabled');
    } else {
      button.setAttribute('disabled', 'disabled');
    }
  }

  ogma.events.onNodesUnselected(onSelectionChange);
  ogma.events.onNodesSelected(onSelectionChange);
  ogma.styles.addNodeRule({
    innerStroke: { width: 0.1, scalingMethod: 'scaled' }
  });

  ogma.parse.gexfFromUrl('files/arctic.gexf')
    .then(function (graph) {
      return ogma.setGraph(graph);
    })
    .then(ogma.view.locateGraph)
    .then(function () {
      var colors = ogma.getNodes().getAttribute('color').reduce(function (acc, c) {
        if (c !== undefined) acc[c] = c;
        return acc;
      }, {});
      var legend = document.createElement('div');
      legend.setAttribute('id', 'legend');
      var legendHtml = ['<ul>',
        Object.keys(names).map(function (color) {
          var name = names[color];
          return '<li><div class="color" style="background-color: ' + color + '"></div>' + name + '</li>';
        }).join('\n'),
        '</ul>'].join('\n');

      legend.innerHTML = legendHtml;
      document.body.appendChild(legend);

      var byColor = ogma.getNodes().getAttribute('color')
        .reduce(function (acc, color) {
          acc[color] = [];
          return acc;
        }, {});
      ogma.getNodes().forEach(function (n) {
        byColor[n.getAttribute('color')].push(n.getId());
      });
      Object.keys(byColor).forEach(function (color) {
        ogma.getNodes(byColor[color]).fillData('groupId', color);
      });
    });

  var transformation = null;
  function toggleGroup() {
    if (transformation === null) {
      transformation = ogma.transformations.addNodeGrouping({
        groupIdFunction: function (node) {
          return node.getData('groupId');
        },
        nodeGenerator: function (nodes, groupId) {
          return {
            id: 'special group ' + groupId,
            data: {
              groupId: groupId,
            },
            attributes: {
              text: names[groupId] || 'Other',
              color: groupId,
              opacity: 0.32
            }
          };
        },
        edgeGenerator: function (edges, id) {
          return {
            id: id,
            attributes: {
              // logarithmic scale for the grouped edges width
              width: 1 + Math.log(edges.size),
              opacity: 0.5
            }
          };
        },
        showContents: function (metaNode) {
          return true;
        },
        onCreated: function (metaNode, visible, subNodes, subEdges) {
          if (visible) {
            subNodes.setAttributes(
              Ogma.geometry.computeCentroid(subNodes.getAttributes(['x', 'y']))
            );
            return ogma.layouts.force({
              nodes: subNodes,
              duration: 0,
              useWebWorkers: false
            })
          }
        }
      });
      transformation.whenApplied().then(function () {
        toggleButton(true);
        return layoutGraph();
      });
    } else {
      transformation.toggle().then(function () {
        if (transformation.isEnabled()) {
          toggleButton(true);
          return layoutGraph();
        } else {
          toggleButton(false);
        }
      });
    }
  }

  function layoutGroup() {
    ogma.layouts.force({ nodes: ogma.getSelectedNodes().getSubNodes()[0] });
  }

  function layoutGraph() {
    return ogma.layouts.force({
      // parameters selected for speed and similarity
      // to the initial layout
      steps: 150,
      charge: 0.125,
      gravity: 0.01,
      edgeStrength: 1,
      theta: 0.9,
      locate: true
    });
  }

</script>

</html>