Search

Layouts

Layouts

Explore different layout options for displaying data.

Layouts
View live example →

Layouts give spatial positions to nodes to help with pattern recognition and other user interactions.

Organic

The default layout, highly optimised for great performance on large datasets. The organic layout excels at untangling big networks and intuitively adapts to updates in the network with as little changes to the overall graph as possible.

Sequential

Arranges nodes in a way that minimises link crossings and makes the most of the available screen space. Useful when nodes are grouped in distinct levels, with a clear sequence of links from one level to the next. Learn more in the Sequential Layouts demo.

Hierarchy

Arranges nodes in a tree-like hierarchical structure. Useful for data such as class diagrams, ontologies and family trees. The hierarchy can be automatically calculated from a given node, or explicitly defined in the data.

Lens

Lays out nodes in a circle with more densely-connected nodes pushed towards the centre and less densely-connected nodes pushed to the edges.

Radial

Gives an 'egocentric' view of the network, best thought of as a circular tree-like structure. Nodes are placed in concentric rings based on how well connected they are to a specified node, with better connected items closer to the centre. This layout is useful for seeing the relationships of individual nodes.

Structural

Groups nodes that are linked to the same set of nodes together. Useful with data with a complex structure.

Key function used:

import KeyLines from "keylines";
import { data } from "./data.js";

let chart;
const orientationEl = document.getElementById("orientation");
const tightnessEl = document.getElementById("slider");

// Gets the top nodes for Radial and Hierarchy layouts if no nodes are selected
function getTopNodes() {
  const selectedItemsIds = chart.selection().filter((item) => chart.getItem(item).type === "node");
  return selectedItemsIds.length ? selectedItemsIds : ["2", "5"];
}

// Gets the selected layout name
function getLayoutName() {
  return document.querySelector('input[name="layoutName"]:checked').value;
}

function layout() {
  // Use the currently selected layout name and options for the layout
  const layoutName = getLayoutName();
  const orientation = orientationEl.options[orientationEl.selectedIndex].value;
  const tightness = parseFloat(tightnessEl.value);

  let options;
  switch (layoutName) {
    case "radial":
      options = { top: getTopNodes(), tightness };
      break;
    case "hierarchy":
      options = { top: getTopNodes(), orientation, tightness };
      break;
    case "sequential":
      options = { top: getTopNodes(), orientation, tightness };
      break;
    default:
      options = { tightness };
      break;
  }
  chart.layout(layoutName, options);
}

function initialiseInteractions() {
  // Run a layout based on current selected menu options
  document.getElementById("layout").addEventListener("click", layout);

  // Run applicable layout when orientation selection changes
  orientationEl.addEventListener("change", () => {
    const layoutName = getLayoutName();
    if (layoutName === "hierarchy" || layoutName === "sequential") {
      layout();
    }
  });

  // Run a layout when tightness selection changes and update the menu display
  tightnessEl.addEventListener("change", () => {
    const tightnessValue = tightnessEl.value;
    document.getElementById("tightnessValue").innerHTML = ` ${tightnessValue}`;
    layout();
  });
}

async function loadKeyLines() {
  const options = {
    drag: {
      links: false,
    },
    logo: { u: "/images/Logo.png" },
    handMode: true,
  };
  chart = await KeyLines.create({ container: "klchart", options });
  chart.load(data);
  chart.layout();
  initialiseInteractions();
}

window.addEventListener("DOMContentLoaded", loadKeyLines);
export const data = {
  type: "LinkChart",
  items: [
    {
      type: "link",
      id: "3-5",
      id1: "3",
      id2: "5",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "3-7",
      id1: "3",
      id2: "7",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "3-9",
      id1: "3",
      id2: "9",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "3-11",
      id1: "3",
      id2: "11",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "5-15",
      id1: "5",
      id2: "15",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "5-23",
      id1: "5",
      id2: "23",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "5-29",
      id1: "5",
      id2: "29",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "15-13",
      id1: "15",
      id2: "13",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "15-17",
      id1: "15",
      id2: "17",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "15-19",
      id1: "15",
      id2: "19",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "15-21",
      id1: "15",
      id2: "21",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-35",
      id1: "29",
      id2: "35",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-25",
      id1: "29",
      id2: "25",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-27",
      id1: "29",
      id2: "27",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-31",
      id1: "29",
      id2: "31",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-33",
      id1: "29",
      id2: "33",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-37",
      id1: "29",
      id2: "37",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "29-39",
      id1: "29",
      id2: "39",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "2-4",
      id1: "2",
      id2: "4",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "2-6",
      id1: "2",
      id2: "6",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "2-8",
      id1: "2",
      id2: "8",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "2-10",
      id1: "2",
      id2: "10",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "2-12",
      id1: "2",
      id2: "12",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "2-14",
      id1: "2",
      id2: "14",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "4-16",
      id1: "4",
      id2: "16",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "4-18",
      id1: "4",
      id2: "18",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "4-20",
      id1: "4",
      id2: "20",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "4-22",
      id1: "4",
      id2: "22",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "6-26",
      id1: "6",
      id2: "26",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "link",
      id: "6-28",
      id1: "6",
      id2: "28",
      c: "#b09fc9",
      w: 4,
      off: 0,
    },
    {
      type: "node",
      id: "2",
      c: "#6E6ED0",
    },
    {
      type: "node",
      id: "3",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "4",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "5",
      c: "#6E6ED0",
    },
    {
      type: "node",
      id: "6",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "7",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "8",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "9",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "10",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "11",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "12",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "13",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "14",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "15",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "16",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "17",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "18",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "19",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "20",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "21",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "22",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "23",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "25",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "26",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "27",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "28",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "29",
      c: "#ff8d00",
    },
    {
      type: "node",
      id: "31",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "33",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "35",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "37",
      c: "#64BC64",
    },
    {
      type: "node",
      id: "39",
      c: "#64BC64",
    },
  ],
};
<!doctype html>
<html lang="en" style="background-color: #2d383f">
  <head>
    <meta charset="utf-8" />
    <title>Layouts</title>
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div id="klchart" class="klchart"></div>
    <script type="module" src="./code.js"></script>
  </body>
</html>
input[type="range"] {
  width: 100%;
  margin-bottom: 10px;
}
.label-alpha,
.label-beta {
  margin-left: 12px;
}
#layoutfieldset {
  margin-left: 10px;
}
fieldset {
  width: 90%;
  margin-top: 5px;
}
fieldset .radio {
  display: block;
  padding-left: 0px;
}

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.