Skip to content
  1. Examples

Node snapping

This example shows how to use the snapping tool, which allows to align nodes while dragging them.

Drag nodes around to see the snapping in action.

ts
import Ogma from '@linkurious/ogma';

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

ogma.generate
  .random({
    nodes: 15,
    edges: 0
  })
  .then(graph => {
    const min = 1,
      max = 10;
    graph.nodes.forEach((n, i) => {
      n.attributes!.text = 'Node ' + i;
      n.attributes!.radius = min + (max - min) * Math.random();
    });
    const loadIndicator = document.getElementById('load')!;
    ogma.setGraph(graph);
    loadIndicator.parentElement!.removeChild(loadIndicator);
    ogma.view.locateGraph();
    //ogma.setOptions({ interactions: { drag: { snapping: { enabled: true, neighbours: false }}}});
  });

const applySettings = () => {
  const snapping = document.getElementById('snapping') as HTMLInputElement;
  const distance = document.getElementById('distance') as HTMLInputElement;
  const neighbours = document.getElementById('neighbours') as HTMLInputElement;

  const enabled = snapping.checked;

  distance.disabled = !enabled;
  neighbours.disabled = !enabled;

  if (enabled) {
    ogma.tools.snapping.enable({
      neighbours: { enabled: neighbours.checked },
      preferredDistance: { enabled: distance.checked }
    });
  } else ogma.tools.snapping.disable();
};

document.getElementById('control')!.addEventListener('change', applySettings);
applySettings();
html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Snapping tool</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
      rel="stylesheet"
    />
    <link type="text/css" rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div id="graph-container"></div>
    <span id="load">Loading...</span>
    <form id="control">
      <ul>
        <li>
          <label
            ><input type="checkbox" id="snapping" checked />
            <strong>Snapping</strong></label
          >
          <ul>
            <li>
              <label
                ><input type="checkbox" id="distance" checked /> Preferred node
                distance</label
              >
            </li>
            <li>
              <label
                ><input type="checkbox" id="neighbours" checked /> Equal
                distribution</label
              >
            </li>
          </ul>
        </li>
      </ul>
    </form>
    <script type="module" src="index.ts"></script>
  </body>
</html>
css
html,
body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  font-family: 'IBM Plex Sans', Arial, sans-serif;
  font-size: 14px;
}

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

#load {
  position: absolute;
  top: 0;
  left: 0;
  padding: 5px;
  color: #fff;
  background: #141229;
  font-size: 12px;
  font-family: monospace;
}

#control {
  background: #ffffff;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
  border-radius: 4px;
  position: absolute;
  top: 2em;
  right: 2em;
  padding: 1em;
  z-index: 10;
}
#control label {
  display: block;
}

#control label.disabled {
  color: #cccccc;
}

#control ul {
  list-style: none;
  padding-left: 10px;
}

#control ul ul {
  margin-top: 10px;
}