Search

Detail on Zoom

Large Charts

Reveal more details as you zoom in on the badge nodes.

Detail on Zoom
View live example →

This demo shows how badge nodes adapt to different zoom levels to always show the right level of detail. Badge nodes are a popular node design that features rectangular nodes with multiple labels inside.

To create rectangular nodes, set the dimensions of your nodes in the w and h properties.

Multiple node labels and custom label styling are currently in beta. KeyLines lets you pass an array of label objects in the t property, where each object is a separate label with a possibility of custom styling.

Adaptive styling in KeyLines is on by default. During zooming, KeyLines automatically fades or reveals labels based on their size and styling, so that each zoom level shows the optimal level of information in terms of readability and information density.

Key functions used:

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

let chart;

async function startKeyLines() {
  const options = {
    handMode: true,
    selectedNode: { b: "#FF9933" },
    iconFontFamily: "Font Awesome 5 Free",
  };

  chart = await KeyLines.create({ container: "klchart", options });

  chart.load({ type: "LinkChart", items: data() });
  await chart.layout("organic", { tightness: 6 });
}

function loadWebFonts() {
  document.fonts.load('24px "Font Awesome 5 Free"').then(startKeyLines);
}

window.addEventListener("DOMContentLoaded", loadWebFonts);
import KeyLines from "keylines";
const COLOUR_BORDER = "#eed3c0";
const COLOUR_LINK = "#3f4238";
const COLOUR_NODE = "#ffe8d6";
const COLOUR_ICON = "#cb997e";
const COLOUR_TEXT = "#441A04";
const TRANSPARENT = "rgba(0,0,0,0)";

export function data() {
  const nodes = [];
  const links = [];

  dataset.forEach((data) => {
    nodes.push(node(data));
    if (data.reportsTo) {
      links.push(link(data));
    }
  });

  return [...nodes, ...links];
}

function node(data) {
  return {
    id: "node" + data.id,
    type: "node",
    b: COLOUR_BORDER,
    bw: 3,
    borderRadius: "10 10 30 10",
    c: COLOUR_NODE,
    d: data,
    fbc: TRANSPARENT,
    t: labels(data),
    h: "auto",
    w: "auto",
  };
}

function link(data) {
  return {
    id: `link${data.id}-${data.reportsTo}`,
    type: "link",
    id1: `node${data.id}`,
    id2: `node${data.reportsTo}`,
    c: COLOUR_LINK,
    w: 2,
    a1: true,
  };
}

export function labels(data) {
  const textStartPosition = 45;
  const smallFontSize = 5;
  return [
    {
      fc: COLOUR_ICON,
      fi: { t: "fas fa-user" },
      fs: 40,
      padding: { left: 10 },
      position: position(0, "middle"),
    },
    {
      fb: true,
      fc: COLOUR_TEXT,
      fs: smallFontSize,
      t: `ID: ${data.id}`,
      position: position(textStartPosition, 10),
    },
    {
      fb: true,
      fc: COLOUR_TEXT,
      fs: 14,
      t: data.name,
      padding: { right: 10 },
      position: position(textStartPosition, 18),
    },
    {
      fc: COLOUR_TEXT,
      fs: smallFontSize,
      t: data.role.toUpperCase(),
      position: position(textStartPosition, 35),
    },
    {
      fb: true,
      fc: COLOUR_TEXT,
      fs: smallFontSize,
      t: `Joined ${data.joined}`,
      padding: { bottom: 10 },
      position: position(textStartPosition, 42),
    },
  ];
}

function position(hor, ver) {
  return {
    horizontal: hor,
    vertical: ver,
  };
}

const dataset = [
  {
    id: "GB90828",
    name: "Dwayne Baumbach",
    role: "Applications Developer",
    joined: "30 September 2018",
    reportsTo: "GB75698",
  },
  {
    id: "GB03290",
    name: "Zobuhle Mdzinwa",
    role: "Chief Analytics Officer",
    joined: "8 December 2019",
    reportsTo: "GB00001",
  },
  {
    id: "GB00001",
    name: "Ike Zimuzor",
    role: "Chief Executive Officer",
    joined: "8 January 2018",
    reportsTo: "",
  },
  {
    id: "GB94123",
    name: "Abdulrahman Azeez",
    role: "Chief Information Security Officer",
    joined: "13 September 2018",
    reportsTo: "GB00001",
  },
  {
    id: "GB36240",
    name: "Florence Thalassa",
    role: "Chief Technical Officer",
    joined: "16 June 2018",
    reportsTo: "GB00001",
  },
  {
    id: "GB95365",
    name: "Azubuike Okafor",
    role: "Database Administrator",
    joined: "7 April 2019",
    reportsTo: "GB51920",
  },
  {
    id: "GB37295",
    name: "Teddie Nigel",
    role: "Database Administrator",
    joined: "21 November 2021",
    reportsTo: "GB75698",
  },
  {
    id: "GB51920",
    name: "Ebenezer Chukwuka",
    role: "Development Manager",
    joined: "30 January 2019",
    reportsTo: "GB36240",
  },
  {
    id: "GB75698",
    name: "Gareth Foster",
    role: "Development Manager",
    joined: "3 February 2019",
    reportsTo: "GB36240",
  },
  {
    id: "GB80207",
    name: "Doris Pardo",
    role: "Development Manager",
    joined: "14 November 2021",
    reportsTo: "GB36240",
  },
  {
    id: "GB16640",
    name: "Adeyemi Temitope",
    role: "DevOps Engineer",
    joined: "10 October 2021",
    reportsTo: "GB51920",
  },
  {
    id: "GB20934",
    name: "Kyson Symons",
    role: "DevOps Engineer",
    joined: "19 April 2020",
    reportsTo: "GB80207",
  },
  {
    id: "GB25567",
    name: "Olufunmilayo Ayodele",
    role: "Head of Product",
    joined: "6 February 2020",
    reportsTo: "GB00001",
  },
  {
    id: "GB88416",
    name: "Steven Malcolm",
    role: "Head of Research",
    joined: "3 January 2021",
    reportsTo: "GB00001",
  },
  {
    id: "GB10004",
    name: "Ismaël Power",
    role: "Junior Data Analyst",
    joined: "18 January 2021",
    reportsTo: "GB18918",
  },
  {
    id: "GB29391",
    name: "Andréa Albring",
    role: "Junior Data Analyst",
    joined: "22 August 2021",
    reportsTo: "GB18918",
  },
  {
    id: "GB11106",
    name: "Allison Chatham",
    role: "Junior Data Scientist",
    joined: "21 January 2021",
    reportsTo: "GB70193",
  },
  {
    id: "GB95440",
    name: "Derdriu Jensen",
    role: "Junior Data Scientist",
    joined: "15 October 2021",
    reportsTo: "GB70193",
  },
  {
    id: "GB29188",
    name: "Caitlin Vincent",
    role: "Junior QA Engineer",
    joined: "19 February 2020",
    reportsTo: "GB14436",
  },
  {
    id: "GB87732",
    name: "Maximilianus Hunter",
    role: "Junior QA Engineer",
    joined: "24 May 2021",
    reportsTo: "GB14436",
  },
  {
    id: "GB86200",
    name: "Olesya Ó Maoláin",
    role: "Junior QA Engineer",
    joined: "29 December 2021",
    reportsTo: "GB36975",
  },
  {
    id: "GB06862",
    name: "Puneet Chaudhari",
    role: "Junior Security Analyst",
    joined: "16 December 2020",
    reportsTo: "GB98226",
  },
  {
    id: "GB33750",
    name: "Aineias MacFarlane",
    role: "Junior Security Technician",
    joined: "9 March 2021",
    reportsTo: "GB97928",
  },
  {
    id: "GB72578",
    name: "Nishant Mhasalkar",
    role: "Junior Security Technician",
    joined: "9 May 2021",
    reportsTo: "GB97928",
  },
  {
    id: "GB91107",
    name: "Honoré Robert",
    role: "Junior Software Engineer",
    joined: "18 August 2021",
    reportsTo: "GB35603",
  },
  {
    id: "GB48827",
    name: "Siobhan Vale",
    role: "Junior Software Engineer",
    joined: "25 July 2021",
    reportsTo: "GB93451",
  },
  {
    id: "GB04632",
    name: "Coline Acquati",
    role: "Junior Software Engineer",
    joined: "30 December 2021",
    reportsTo: "GB78631",
  },
  {
    id: "GB04882",
    name: "Sofía Strange",
    role: "Junior UI/UX Developer",
    joined: "16 March 2021",
    reportsTo: "GB09150",
  },
  {
    id: "GB06220",
    name: "Devadas Montana",
    role: "Junior UI/UX Developer",
    joined: "27 January 2021",
    reportsTo: "GB09150",
  },
  {
    id: "GB17731",
    name: "Amir Roberts",
    role: "Junior UI/UX Developer",
    joined: "10 May 2021",
    reportsTo: "GB93307",
  },
  {
    id: "GB34819",
    name: "Jagoda Beran",
    role: "Junior UI/UX Developer",
    joined: "26 February 2021",
    reportsTo: "GB93307",
  },
  {
    id: "GB70657",
    name: "Marlene Löfgren",
    role: "Network Engineer",
    joined: "3 November 2019",
    reportsTo: "GB51920",
  },
  {
    id: "GB01479",
    name: "Georgette Hewitt",
    role: "Network Engineer",
    joined: "13 July 2020",
    reportsTo: "GB75698",
  },
  {
    id: "GB09094",
    name: "Camilla Berger",
    role: "Network Engineer",
    joined: "14 November 2021",
    reportsTo: "GB75698",
  },
  {
    id: "GB07025",
    name: "Sefu Mwangi",
    role: "Product Manager",
    joined: "21 October 2018",
    reportsTo: "GB25567",
  },
  {
    id: "GB11777",
    name: "Gale Overton",
    role: "Product Manager",
    joined: "3 October 2019",
    reportsTo: "GB25567",
  },
  {
    id: "GB12437",
    name: "Simone Binalay",
    role: "Research Technician",
    joined: "25 September 2019",
    reportsTo: "GB88416",
  },
  {
    id: "GB56066",
    name: "Divya Danniel",
    role: "Research Technician",
    joined: "1 August 2019",
    reportsTo: "GB88416",
  },
  {
    id: "GB36529",
    name: "Adalberto Nazarian",
    role: "Research Technician",
    joined: "7 July 2019",
    reportsTo: "GB88416",
  },
  {
    id: "GB51109",
    name: "Eryn Goldschmidt",
    role: "Junior Security Analyst",
    joined: "21 August 2018",
    reportsTo: "GB98226",
  },
  {
    id: "GB18918",
    name: "Roshni Aiello",
    role: "Senior Data Analyst",
    joined: "30 July 2019",
    reportsTo: "GB03290",
  },
  {
    id: "GB70193",
    name: "Athaliah Daniel",
    role: "Senior Data Scientist",
    joined: "15 November 2020",
    reportsTo: "GB03290",
  },
  {
    id: "GB14436",
    name: "Kwame Ofori-Darko",
    role: "Senior QA Engineer",
    joined: "24 September 2020",
    reportsTo: "GB51920",
  },
  {
    id: "GB36975",
    name: "Constantino Beck",
    role: "Senior QA Engineer",
    joined: "16 September 2020",
    reportsTo: "GB75698",
  },
  {
    id: "GB98226",
    name: "Vojtech Bray",
    role: "Senior Security Analyst",
    joined: "12 December 2018",
    reportsTo: "GB94123",
  },
  {
    id: "GB97928",
    name: "Idris Tukala",
    role: "Senior Security Technician",
    joined: "27 October 2019",
    reportsTo: "GB94123",
  },
  {
    id: "GB35603",
    name: "Frederick Hernandez",
    role: "Senior Software Engineer",
    joined: "5 February 2019",
    reportsTo: "GB51920",
  },
  {
    id: "GB93451",
    name: "Ihintza Sugiura",
    role: "Senior Software Engineer",
    joined: "20 August 2019",
    reportsTo: "GB80207",
  },
  {
    id: "GB11916",
    name: "Rhianna Stacy",
    role: "Senior Software Engineer",
    joined: "20 September 2018",
    reportsTo: "GB80207",
  },
  {
    id: "GB78631",
    name: "Nadia Patel",
    role: "Senior Software Engineer",
    joined: "16 June 2019",
    reportsTo: "GB51920",
  },
  {
    id: "GB09150",
    name: "Priscilla Marchand",
    role: "Senior UI/UX Developer",
    joined: "13 July 2021",
    reportsTo: "GB07025",
  },
  {
    id: "GB93307",
    name: "Annabel Devin",
    role: "Senior UI/UX Developer",
    joined: "29 April 2018",
    reportsTo: "GB07025",
  },
  {
    id: "GB37948",
    name: "Cecilia Mills",
    role: "Solutions Architect",
    joined: "30 December 2019",
    reportsTo: "GB80207",
  },
  {
    id: "GB35153",
    name: "Junichi Sugimori",
    role: "Solutions Architect",
    joined: "18 January 2021",
    reportsTo: "GB51920",
  },
  {
    id: "GB96519",
    name: "Imran Ashok",
    role: "Technical Writer",
    joined: "21 November 2021",
    reportsTo: "GB51920",
  },
  {
    id: "GB03489",
    name: "Xaviera Rosenfeld",
    role: "Technical Writer",
    joined: "3 November 2021",
    reportsTo: "GB75698",
  },
  {
    id: "GB67199",
    name: "Sunday Beaumont",
    role: "Technical Writer",
    joined: "20 April 2020",
    reportsTo: "GB80207",
  },
  {
    id: "GB24476",
    name: "Stuart Barber",
    role: "Web Developer",
    joined: "22 September 2020",
    reportsTo: "GB75698",
  },
  {
    id: "GB52104",
    name: "Mollie Gaspari",
    role: "Web Developer",
    joined: "24 September 2019",
    reportsTo: "GB80207",
  },
];
<!doctype html>
<html lang="en" style="background-color: #2d383f">
  <head>
    <meta charset="utf-8" />
    <title>Detail on Zoom</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"
      type="text/css"
      href="@fortawesome/[email protected]/css/fontawesome.css"
    />
    <link
      rel="stylesheet"
      type="text/css"
      href="@fortawesome/[email protected]/css/solid.css"
    />
  </head>
  <body>
    <div id="klchart" class="klchart"></div>
    <script type="module" src="./code.js"></script>
  </body>
</html>

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.