Skip to content
  1. Examples

Radial

This example shows how to use the radial layout.It positions nodes around the selected one based on their graph-theoretical distance (shortest path in the graph, connecting them). If there are subgraphs or nodes not reachable from the central node, they will be pushed outwards, but still placed around the layout in a readable way.

ts
import Ogma, { NodeId } from '@linkurious/ogma';

const ogma = new Ogma({
  container: 'graph-container'
});

const run = (
  centralNodeId: NodeId,
  animate: boolean,
  overlap: boolean,
  randomize: boolean
) => {
  console.time('radial stress');
  ogma.layouts
    .radial({
      centralNode: centralNodeId,
      renderSteps: animate,
      randomize: randomize,
      allowOverlap: overlap,
      maxIterations: 200
    })
    .then(() => {
      console.timeEnd('radial stress');
      ogma.view.locateGraph({
        easing: 'linear',
        duration: 200
      });
    });
};

Ogma.parse
  .gexfFromUrl('karate.gexf')
  .then(g => ogma.setGraph(g))
  .then(() => ogma.view.locateGraph())
  .then(() => {
    document.querySelector('#layout')!.addEventListener('click', evt => {
      evt.preventDefault();
      const form = document.querySelector<HTMLFormElement>('#focus-select')!;
      const focusInput = Array.prototype.filter.call(form['focus'], input => {
        return input.checked;
      })[0];
      const focusNode = focusInput.value;
      // @ts-expect-error
      const animate = form['animate'].checked;
      const overlap = form['overlap'].checked;
      const randomize = form['randomize'].checked;
      run(focusNode, animate, overlap, randomize);
    });
  });
html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />

    <link type="text/css" rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div id="graph-container"></div>
    <form id="focus-select" class="control-bar panel">
      <div class="content">
        <label
          ><input type="radio" name="focus" checked value="1.0" />
          Instructor</label
        >
        <label
          ><input type="radio" name="focus" value="34.0" /> Administrator</label
        >
        <label
          ><input type="checkbox" name="overlap" /> allow nodes overlap</label
        >
        <label><input type="checkbox" name="animate" /> animate</label>
        <label><input type="checkbox" name="randomize" /> randomize</label>
      </div>
      <div class="controls">
        <button id="layout">Run</button>
      </div>
    </form>
    <script type="module" src="index.ts"></script>
  </body>
</html>
css
html,
body {
  font-family: 'Inter', sans-serif;
}

:root {
  --base-color: #4999f7;
  --active-color: var(--base-color);
  --gray: #d9d9d9;
  --white: #ffffff;
  --lighter-gray: #f4f4f4;
  --light-gray: #e6e6e6;
  --inactive-color: #cee5ff;
  --group-color: #525fe1;
  --group-inactive-color: #c2c8ff;
  --selection-color: #04ddcb;
  --darker-gray: #b6b6b6;
  --dark-gray: #555;
  --dark-color: #3a3535;
  --edge-color: var(--dark-color);
  --border-radius: 5px;
  --button-border-radius: var(--border-radius);
  --edge-inactive-color: var(--light-gray);
  --button-background-color: #ffffff;
  --shadow-color: rgba(0, 0, 0, 0.25);
  --shadow-hover-color: rgba(0, 0, 0, 0.5);
  --button-shadow: 0 0 4px var(--shadow-color);
  --button-shadow-hover: 0 0 4px var(--shadow-hover-color);
  --button-icon-color: #000000;
  --button-icon-hover-color: var(--active-color);
}

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

.ui {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: 0.5em;
}

#custom-group-btn {
  top: 40px;
}

.panel {
  background: var(--button-background-color);
  border-radius: var(--button-border-radius);
  box-shadow: var(--button-shadow);
  padding: 10px;
}

.panel {
  position: absolute;
}

.panel h2 {
  text-transform: uppercase;
  font-weight: 400;
  font-size: 14px;
  margin: 0;
}

.panel {
  margin-top: 1px;
  padding: 5px 10px;
}

.panel button {
  background: var(--button-background-color);
  border: none;
  border-radius: var(--button-border-radius);
  border-color: var(--shadow-color);
  padding: 5px 10px;
  cursor: pointer;
  width: 100%;
  color: var(--dark-gray);
  border: 1px solid var(--light-gray);
}

.panel button:hover {
  background: var(--lighter-gray);
  border: 1px solid var(--darker-gray);
}

.panel button[disabled] {
  color: var(--light-gray);
  border: 1px solid var(--light-gray);
  background-color: var(--lighter-gray);
}

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

#focus-select {
  position: absolute;
  top: 20px;
  right: 20px;
  padding: 10px;
  background: white;
  z-index: 400;
  width: 200px;
  right: 1em;
  top: 1em;
}

#focus-select label {
  display: block;
}

#focus-select .controls {
  text-align: center;
  margin-top: 10px;
}

#focus-select .content {
  line-height: 1.5em;
}

.control-bar {
  font-family: Helvetica, Arial, sans-serif;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
  border-radius: 4px;
}