Styled links make connections in your data visualisations clearer and more meaningful.
This demo demonstrates popular styling options that you can use.The JavaScript for each individual link is available on the right-hand side, so you can easily copy and reuse the code in your KeyLines project.
Double-clicking or double-tapping the chart background will zoom the viewport to fit the chart.
Object types used:
Key functions used:
import KeyLines from "keylines";
import { data } from "./data.js";
let chart;
let doAnts = false;
// Alter the view by zooming to the 'fit' position
function fitZoom(animate) {
chart.zoom("fit", { animate, time: 500 });
}
// Format the properties of the displayed item (may accept a nav control id)
function prettyPrint() {
const id = chart.selection()[0];
const item = chart.getItem(id);
if (item) {
// Avoid printing the coordinates of the elements in the display window
delete item.x;
delete item.y;
document.getElementById("display").innerHTML = JSON.stringify(item, null, 1);
} else if (!id) {
// If the background was clicked, clear the selection
document.getElementById("display").innerHTML = "No item selected";
}
}
function toggleAnts() {
doAnts = !doAnts;
// Update the flow property of the nodes having an id
// that starts with 'flow'.
chart.each({ type: "link" }, (link) => {
if (link.d && link.d.flow) {
chart.setProperties({ id: link.id, flow: doAnts ? { velocity: link.d.flow } : undefined });
}
});
// Update the source code displayed to reflect the flow changes.
prettyPrint();
}
function initializeInteractions() {
// When clicking on an item, show its properties on the right-hand side
chart.on("selection-change", prettyPrint);
// Zoom the view to its original position when double-clicking the background
chart.on("double-click", ({ id, preventDefault }) => {
if (!chart.getItem(id)) {
fitZoom(true);
}
// Default behaviour is to zoom in - we preventDefault to override this
preventDefault();
});
// prevent nodes from being dragged
chart.on("drag-start", ({ setDragOptions, type }) => {
if (type === "node") {
setDragOptions({ type: chart.options().handMode ? "pan" : "marquee" });
}
});
const inlineElement = document.getElementById("inlineEnabled");
document.getElementById("flowEnabled").addEventListener("change", toggleAnts);
inlineElement.addEventListener("change", () => {
chart.options({
linkStyle: {
inline: !!inlineElement.checked,
},
});
});
}
async function loadKeylines() {
const options = {
logo: { u: "/images/Logo.png" },
selectionColour: "#FF9933",
selfLinks: true,
overview: { icon: false },
handMode: true,
};
chart = await KeyLines.create({ container: "klchart", options });
chart.load(data); // load the chart data
fitZoom(); // adjust the view to 'fit' the displayed chart
initializeInteractions(); // Attach the chart and user events
}
window.addEventListener("DOMContentLoaded", loadKeylines); const primaryColour = "rgb(3,169,244)";
const darkColour = "#0288D1";
const lightColour = "#B3E5FC";
const primaryTransparent = "rgba(3,169,244,0.4)";
const accentColour = "#FFEB3B";
const grayColour = "#BDBDBD";
const backgroundColour = "#FFF";
const transparentColour = "rgba(255,255,255,0)";
export const data = {
type: "LinkChart",
items: [
{ type: "node", id: "1_n0", c: transparentColour, x: 225, y: 65, t: "Solid" },
{ type: "node", id: "1_n1", c: primaryColour, x: 150, y: 100 },
{ type: "node", id: "1_n2", c: primaryColour, x: 300, y: 100 },
{ type: "link", id: "1_l1", id1: "1_n1", id2: "1_n2", c: grayColour, w: 2 },
{ type: "node", id: "2_n0", c: transparentColour, x: 225, y: 165, t: "Dashed" },
{ type: "node", id: "2_n1", c: primaryColour, x: 150, y: 200 },
{ type: "node", id: "2_n2", c: primaryColour, x: 300, y: 200 },
{ type: "link", id: "2_l2", id1: "2_n2", id2: "2_n1", c: grayColour, ls: "dashed", w: 4 },
{ type: "node", id: "3_n0", c: transparentColour, x: 225, y: 265, t: "Dotted" },
{ type: "node", id: "3_n1", c: primaryColour, x: 150, y: 300 },
{ type: "node", id: "3_n2", c: primaryColour, x: 300, y: 300 },
{ type: "link", id: "3_l1", id1: "3_n1", id2: "3_n2", c: grayColour, ls: "dotted", w: 4 },
{ type: "node", id: "4_n0", c: transparentColour, x: 225, y: 365, t: "Unidirectional" },
{ type: "node", id: "4_n1", c: primaryColour, x: 150, y: 400 },
{ type: "node", id: "4_n2", c: primaryColour, x: 300, y: 400 },
{
type: "link",
id: "4_l1",
id1: "4_n1",
id2: "4_n2",
a2: true,
c: grayColour,
d: { flow: true },
},
{ type: "node", id: "5_n0", c: transparentColour, x: 225, y: 465, t: "Bidirectional" },
{ type: "node", id: "5_n1", c: primaryColour, x: 150, y: 500 },
{ type: "node", id: "5_n2", c: primaryColour, x: 300, y: 500 },
{
type: "link",
id: "5_l1",
id1: "5_n1",
id2: "5_n2",
a1: true,
a2: true,
c: grayColour,
d: { flow: true },
},
{ type: "node", id: "6_n0", c: transparentColour, x: 475, y: 65, t: "Glyphs" },
{ type: "node", id: "6_n1", c: primaryColour, x: 400, y: 100 },
{ type: "node", id: "6_n2", c: primaryColour, x: 550, y: 100 },
{
type: "link",
id: "6_l1",
id1: "6_n1",
id2: "6_n2",
a1: false,
a2: false,
c: grayColour,
g: [{ t: "1", c: grayColour, border: { width: 1, colour: "#F9BF3B" } }],
t1: { g: [{ c: "#F9BF3B", b: transparentColour, fc: "black" }] },
t2: { g: [{ u: "/images/glyphs/warning_48.png" }] },
},
{ type: "node", id: "7_n0", c: transparentColour, x: 475, y: 165, t: "Back-off distance" },
{ type: "node", id: "7_n1", c: primaryColour, x: 400, y: 200 },
{ type: "node", id: "7_n2", c: primaryColour, x: 550, y: 200 },
{
type: "link",
id: "7_l1",
id1: "7_n1",
id2: "7_n2",
a1: true,
a2: true,
b1: 0.25,
b2: 0.25,
c: grayColour,
},
{ type: "node", id: "8_n0", c: transparentColour, x: 475, y: 265, t: "Width" },
{ type: "node", id: "8_n1", c: primaryColour, x: 400, y: 300 },
{ type: "node", id: "8_n2", c: primaryColour, x: 550, y: 300 },
{ type: "link", id: "8_l1", id1: "8_n1", id2: "8_n2", a1: true, a2: true, w: 4, c: grayColour },
{ type: "node", id: "9_n0", c: transparentColour, x: 475, y: 365, t: "Colour" },
{ type: "node", id: "9_n1", c: primaryColour, x: 400, y: 400 },
{ type: "node", id: "9_n2", c: primaryColour, x: 550, y: 400 },
{
type: "link",
id: "9_l1",
id1: "9_n1",
id2: "9_n2",
a1: true,
a2: true,
c: accentColour,
d: { flow: 3 },
},
{
type: "link",
id: "9_l2",
id1: "9_n1",
id2: "9_n2",
a1: true,
a2: true,
c: primaryColour,
c2: "rgb(244,83,3)",
d: { flow: 3 },
},
{ type: "node", id: "10_n0", c: transparentColour, x: 475, y: 465, t: "Curved" },
{ type: "node", id: "10_n1", c: primaryColour, x: 400, y: 500 },
{ type: "node", id: "10_n2", c: primaryColour, x: 550, y: 500 },
{
type: "link",
id: "10_l1",
id1: "10_n1",
id2: "10_n2",
a2: true,
c: grayColour,
d: { flow: 3 },
},
{
type: "link",
id: "10_l2",
id1: "10_n2",
id2: "10_n1",
a2: true,
c: grayColour,
d: { flow: 3 },
},
{ type: "node", id: "11_n0", c: transparentColour, x: 650, y: 50, t: "Self link" },
{ type: "node", id: "11_n1", c: primaryColour, x: 650, y: 100 },
{ type: "link", id: "11_l1", id1: "11_n1", id2: "11_n1", a2: true, c: grayColour },
// Hierarchical
{ type: "node", id: "12_n1", c: primaryColour, x: 650, y: 200 },
{ type: "node", id: "12_n2", c: primaryColour, x: 850, y: 100 },
{ type: "node", id: "12_n3", c: primaryColour, x: 850, y: 200 },
{ type: "node", id: "12_n4", c: primaryColour, x: 850, y: 300 },
{
type: "link",
id: "12_l1",
id1: "12_n1",
id2: "12_n2",
a2: true,
c: lightColour,
w: 2,
t: "Link\nLabel",
fb: true,
fbc: lightColour,
fc: darkColour,
border: {},
},
{
type: "link",
id: "12_l2",
id1: "12_n1",
id2: "12_n3",
a2: true,
c: lightColour,
w: 6,
t: "Label",
fb: true,
fbc: accentColour,
fc: darkColour,
fs: 20,
border: { colour: lightColour, width: 1 },
},
{
type: "link",
id: "12_l3",
id1: "12_n1",
id2: "12_n4",
a2: true,
c: lightColour,
w: 2,
t: "Label",
border: { radius: 2 },
fb: true,
fc: primaryColour,
ff: "monospace",
t1: {
t: "End",
fb: true,
fbc: accentColour,
fc: primaryColour,
ff: "monospace",
padding: "2 5 0 5",
border: { radius: 10 },
},
t2: {
t: "End",
fb: true,
fbc: "white",
fc: primaryColour,
ff: "monospace",
border: { colour: primaryColour, radius: 2, width: 1 },
},
},
// Atom style
{ type: "node", id: "13_n1", t: "1", c: primaryColour, x: 750, y: 450 },
{ type: "node", id: "13_n3", t: "3", c: lightColour, e: 0.8, x: 750, y: 350 },
{ type: "node", id: "13_n4", t: "4", c: lightColour, e: 0.8, x: 850, y: 400 },
{
type: "node",
id: "13_n2",
t: "2",
c: backgroundColour,
b: lightColour,
bs: "dashed",
e: 0.8,
x: 650,
y: 400,
},
{
type: "node",
id: "13_n5",
t: "5",
c: backgroundColour,
b: lightColour,
bs: "dashed",
e: 0.8,
x: 850,
y: 500,
},
{ type: "node", id: "13_n7", t: "7", c: lightColour, e: 0.8, x: 650, y: 500 },
{ type: "node", id: "13_n6", t: "6", c: lightColour, e: 0.8, x: 750, y: 550 },
{
type: "link",
id: "l8",
id1: "13_n2",
id2: "13_n3",
c: primaryTransparent,
w: 2,
d: { flow: 10 },
},
{
type: "link",
id: "l9",
id1: "13_n2",
id2: "13_n7",
c: primaryTransparent,
w: 2,
d: { flow: -1 },
},
{
type: "link",
id: "l11",
id1: "13_n7",
id2: "13_n6",
c: primaryTransparent,
w: 2,
d: { flow: 2 },
},
{
type: "link",
id: "l13",
id1: "13_n6",
id2: "13_n5",
c: primaryTransparent,
w: 2,
d: { flow: 3 },
},
{
type: "link",
id: "l15",
id1: "13_n5",
id2: "13_n4",
c: primaryTransparent,
w: 2,
d: { flow: -4 },
},
{
type: "link",
id: "l17",
id1: "13_n4",
id2: "13_n3",
c: primaryTransparent,
w: 2,
d: { flow: 2 },
},
{
type: "link",
id: "l12",
id1: "13_n7",
id2: "13_n5",
c: primaryTransparent,
w: 2,
d: { flow: -3 },
},
{
type: "link",
id: "l16",
id1: "13_n5",
id2: "13_n3",
c: primaryTransparent,
w: 2,
d: { flow: -1 },
},
{
type: "link",
id: "l19",
id1: "13_n7",
id2: "13_n3",
c: primaryTransparent,
w: 2,
d: { flow: 0.5 },
},
{
type: "link",
id: "l14",
id1: "13_n6",
id2: "13_n4",
c: primaryTransparent,
w: 2,
d: { flow: 3.5 },
},
{
type: "link",
id: "l10",
id1: "13_n2",
id2: "13_n6",
c: primaryTransparent,
w: 2,
d: { flow: -3.8 },
},
{
type: "link",
id: "l18",
id1: "13_n4",
id2: "13_n2",
c: primaryTransparent,
w: 2,
d: { flow: -3.5 },
},
{
type: "link",
id: "l1",
id1: "13_n5",
id2: "13_n1",
c: lightColour,
a2: true,
ls: "dashed",
w: 2,
d: { flow: -2 },
},
{
type: "link",
id: "l5",
id1: "13_n7",
id2: "13_n1",
c: primaryTransparent,
w: 2,
d: { flow: 3 },
},
{
type: "link",
id: "l7",
id1: "13_n1",
id2: "13_n6",
c: primaryColour,
a2: true,
w: 6,
d: { flow: 4 },
},
{
type: "link",
id: "l6",
id1: "13_n2",
id2: "13_n1",
c: lightColour,
a2: true,
ls: "dashed",
w: 2,
d: { flow: 3 },
},
{
type: "link",
id: "l2",
id1: "13_n4",
id2: "13_n1",
c: primaryTransparent,
w: 2,
d: { flow: -2.5 },
},
{
type: "link",
id: "l3",
id1: "13_n1",
id2: "13_n3",
c: primaryColour,
a2: true,
w: 6,
d: { flow: 1.8 },
},
],
}; <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Style Links</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" />
</head>
<body>
<div id="klchart" class="klchart"></div>
<script type="module" src="./code.js"></script>
</body>
</html>