This demo illustrates how selected nodes can be forced into patterns to improve intelligibility of a chart.
KeyLines layouts are typically curved and 'organic' to provide an attractive and easy-to-read chart. Sometimes, you might need to cluster a set of nodes together in a particular arrangement.
The demo shows the application of distinctive arrangements (grid, circle and radial) to clearly differentiate the selected and sorted nodes from their peers. The demo also illustrates various sorting options.
You could also think about using combos to group nodes. See the Combo Options demo to see combos in action.
Key functions used:
import KeyLines from "keylines";
import { data } from "./data.js";
let chart;
const tightValueSlider = document.getElementById("slider");
// Returns the selected radio button
// name should be : shape, criteria, or position
function getSelectedRadioButton(name) {
return document.querySelector(`input[name=${name}]:checked`).value;
}
async function doArrange(items) {
const idList = items.map((item) => item.id);
const tightness = +tightValueSlider.value;
const position = getSelectedRadioButton("position");
const options = { tightness, position, fit: true };
await chart.arrange(getSelectedRadioButton("shape"), idList, options);
}
function sortByLabel(items) {
return items.sort((a, b) => a.t.localeCompare(b.t));
}
function sortByValues(items, sortValues) {
return items.slice().sort((a, b) => sortValues[b.id] - sortValues[a.id]);
}
function isNode(item) {
return item && item.type === "node";
}
async function startArrange() {
// Filter nodes from the whole selection
const selectedItems = chart.getItem(chart.selection());
const selectedNodes = selectedItems.filter(isNode);
// Change the selection only to nodes
chart.selection(selectedNodes.map((item) => item.id));
// Get the selected criteria from the right panel
const criteria = getSelectedRadioButton("criteria");
// sort items and arrange them
let orderedList;
switch (criteria) {
case "alpha":
orderedList = sortByLabel(selectedNodes);
break;
case "betweenness":
{
const betweennessValues = await chart.graph().betweenness({});
orderedList = sortByValues(selectedNodes, betweennessValues);
}
break;
case "degree":
{
const degreesValues = chart.graph().degrees();
orderedList = sortByValues(selectedNodes, degreesValues);
}
break;
default:
break;
}
doArrange(orderedList);
}
function updateSliderValue() {
const tightValue = tightValueSlider.value;
document.getElementById("tighValueDisplayed").innerHTML = ` ${tightValue}`;
}
function createEventHandlers() {
const arrangeButton = document.getElementById("arrangeButton");
arrangeButton.addEventListener("click", startArrange);
const layoutButton = document.getElementById("layoutButton");
layoutButton.addEventListener("click", () => chart.layout());
tightValueSlider.addEventListener("input", updateSliderValue);
}
async function loadKeyLines() {
const options = {
drag: {
links: false,
},
logo: "/public/images/Logo.png",
minZoom: 0.01,
};
chart = await KeyLines.create({
id: "kl",
container: "klchart",
options,
});
chart.load(data);
chart.layout();
createEventHandlers();
}
window.addEventListener("DOMContentLoaded", loadKeyLines); const defaultNodeColour = "rgb(253, 141, 60)";
const defaultLinkColour = "rgb(145, 146, 149)";
export const data = {
type: "LinkChart",
items: [
{
type: "node",
id: "343111",
t: "Tamara Williams",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343112",
t: "Joshua Cervantes",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343113",
t: "Larry Anderson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343114",
t: "Michael Solis",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343115",
t: "Maria Barker",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343116",
t: "Justin Patel",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343117",
t: "Richard Evans",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343118",
t: "Julie Chavez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343119",
t: "Denise Wheeler",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343120",
t: "Tracy Fisher",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343121",
t: "Alicia Smith",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343122",
t: "Malik Powell",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343123",
t: "Amy Brady",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343124",
t: "Angela Campbell",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343125",
t: "Kimberly Williams",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343126",
t: "Tina Burton",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343127",
t: "Michael Nicholson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343128",
t: "John Becker",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343129",
t: "Cindy Jenkins",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343130",
t: "Debbie McConnell",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343131",
t: "Robert Mckenzie",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343132",
t: "Michael Osborn",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343133",
t: "Sandra Bush",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343134",
t: "Kyle Garcia",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343135",
t: "Terrence Fitzgerald",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343136",
t: "Kerry Wilson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343137",
t: "Jason Wilson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343138",
t: "Kenneth Davis",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343139",
t: "Lucas Lucero",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343140",
t: "Jesse Hudson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343141",
t: "David Osborne",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343142",
t: "Anthony Shannon",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343143",
t: "Joseph Lopez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343144",
t: "Pamela Gilbert",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343145",
t: "Victoria Aguirre",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343146",
t: "Kristie Hawkins",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343147",
t: "Daniel Chavez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343148",
t: "Kelsey Mitchell",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343149",
t: "Kristen Taylor",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343150",
t: "Kristen Rodriguez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343151",
t: "Tara Marquez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343152",
t: "James Lewis",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343153",
t: "Anthony Robinson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343154",
t: "Alexandra Perez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343155",
t: "Steven Wallace",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343156",
t: "Jennifer Valdez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343157",
t: "Benjamin Erickson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343158",
t: "Travis Chen",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343159",
t: "Jeffrey Kelley",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343160",
t: "Andrew Stout",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343161",
t: "Philip Larson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343162",
t: "Sharon Miller",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343163",
t: "Micheal King",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343164",
t: "Daniel Farmer",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343165",
t: "Hector Stewart",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343166",
t: "Joseph McCoy",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343167",
t: "Michael Mathews",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343168",
t: "Jose Ellison",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343169",
t: "Brandon Jackson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343170",
t: "Edward Hernandez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343171",
t: "Gina Miller",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343172",
t: "Eric Garcia",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343173",
t: "John Bailey",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343174",
t: "Gary Harrison",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343175",
t: "Patrick Newman",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343176",
t: "Rodney Sampson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343177",
t: "Andrea Carter",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343178",
t: "Rhonda Johnson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343179",
t: "Elizabeth Price",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343180",
t: "Ricky Maddox",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343181",
t: "Michael Griffin",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343182",
t: "Anthony Myers",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343183",
t: "Jeremy Burke",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343184",
t: "Tina Reynolds",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343185",
t: "Matthew Banks",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343186",
t: "Brian Rocha",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343187",
t: "Michelle Adams",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343188",
t: "Ronald Clark",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343189",
t: "Kimberly Jones",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343190",
t: "Michele Lyons",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343191",
t: "Debbie Lamb",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343192",
t: "Sandra Wilson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343193",
t: "Peggy Hicks",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343194",
t: "David King",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343195",
t: "Kristopher Lynch",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343196",
t: "Steven Perez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343197",
t: "Michael Wyatt",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343198",
t: "Cody Guerrero",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343199",
t: "Molly Compton",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343200",
t: "Michael Smith",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343201",
t: "Teresa Winters",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343202",
t: "Christopher Lawson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343203",
t: "Stephanie Bell",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343204",
t: "Devon Johnson",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343205",
t: "Eddie Sullivan",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343206",
t: "Benjamin Mitchell",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343207",
t: "Sarah Garner",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343208",
t: "Lisa Miles",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343209",
t: "Lisa Wallace",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343210",
t: "Alex Ross",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343211",
t: "Kenneth Dunlap",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343212",
t: "Juan Rangel",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343213",
t: "Kristin Cook",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343214",
t: "Tami Orozco",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343215",
t: "Julie Sanchez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343216",
t: "Tiffany Page",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343217",
t: "Elizabeth Warner",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343218",
t: "Kayla Bruce",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343219",
t: "Patricia Carroll",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343220",
t: "Mark Edwards",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343221",
t: "David Williams",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343222",
t: "Billy Owen",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343223",
t: "Todd Bright",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343224",
t: "Lisa Burnett",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343225",
t: "Jeffrey Henry",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343226",
t: "David Cooper",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343227",
t: "Jeremy Simon",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343228",
t: "Kimberly Martinez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343229",
t: "Karen Brown",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343230",
t: "Linda Lyons",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343231",
t: "James Lutz",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343232",
t: "Martha Gomez",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343233",
t: "Haley Miller",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
id: "343234",
t: "Melissa Reynolds",
c: defaultNodeColour,
x: 0,
y: 0,
},
{
type: "node",
// ...truncated 3897 lines <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Arrange Items</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>
<div id="applemenumask"></div>
<script type="module" src="./code.js"></script>
</body>
</html>