The right node design can help you visualise any type or amount of data in an intuitive way, provide the best user interface and experience for chart users and integrate your charts seamlessly into any application.
For more details about the advanced styling features in KeyLines, see also our Node and Combo Styling docs.
Custom shaped nodes
Set the width (w) and height (h) of nodes to create rectangular nodes. You can also add one or multiple rounded corners by setting the borderRadius property.
Alternatively, you can get any node shape by overlapping nodes with font icons that are added as labels in the t property array of objects.
Multiple styled labels
The t array of objects can be used to add multiple image, text and font icon labels. Each label can have its own styling and positioning and serve different purposes such as a source of information or an additional node styling feature.
Custom label interactions
Labels can serve as UI elements such as buttons, icons or toggles. Use pointer events and hover events to add custom interactions and interaction styling.
You can also design labels with dynamically changing styling and create your own graphical elements such as progress bars or stack bars.
Images inside labels
To create images on nodes with multiple styled labels, simply set the label's u property.
Key functions used:
import {
data,
invertedInteractiveNode,
normalInteractiveNode,
interactionStylePresets,
} from "./data.js";
import KeyLines from "keylines";
let chart;
// keeps track of the current state/styling of items on the chart
const itemsState = [...data.items];
function highlightSelection(id) {
// if the user hasn't clicked an item resize back to fit
if (!id) {
chart.foreground(() => true);
return;
}
// if there is a clicked item set it to be foregrounded
const clickedItem = chart.getItem(id);
if (clickedItem) {
chart.foreground((item) => clickedItem.id === item.id);
}
}
function formatPrintString(key, value) {
if (key === "x" || key === "y" || key === "bg") {
return undefined;
}
// prints the borderRadius array as a single value if all directions are set to the same value
if (key === "borderRadius") {
const set = new Set(value);
if (set.size === 1) {
return value[0];
}
}
return value;
}
// Formats the code snippets neatly in the display box on the right-hand side
function prettyPrint(id) {
const item = chart.getItem(id);
if (item) {
const json = JSON.stringify(item, formatPrintString, 1);
document.getElementById("display").innerHTML = json;
} else {
document.getElementById("display").innerHTML = "No node selected";
}
}
// Called when KeyLines is created
function initializeInteractions() {
// Zoom the view to its original position when double-clicking the background
chart.on("double-click", ({ id, preventDefault }) => {
if (!chart.getItem(id)) {
chart.zoom("fit", { animate: true, time: 500 });
}
// Default behaviour is to zoom in - we preventDefault to override this
preventDefault();
});
let interactiveNodesState = {};
const labelButtons = {};
const buttonGroupLabels = {};
function registerLabelButton(itemId, labelIndex, onItemInteractionLabelStyle, onClick) {
labelButtons[itemId] = labelButtons[itemId] || {};
labelButtons[itemId][labelIndex] = { onClick };
labelButtons[itemId][onItemInteractionLabelStyle] = onItemInteractionLabelStyle;
}
function registerLabelButtonGroup(itemId, labelIndexArray, onItemInteractionLabelStyle, onClick) {
for (const labelIndex of labelIndexArray) {
registerLabelButton(itemId, labelIndex, onItemInteractionLabelStyle, onClick);
buttonGroupLabels[itemId] = { ...buttonGroupLabels[itemId], [labelIndex]: labelIndexArray };
}
}
// Highlight and pretty print when a selection is made or if we click an interactive label
chart.on("click", ({ id, subItem, preventDefault }) => {
prettyPrint(id);
highlightSelection(id);
if (subItem.type === "label") {
const labelIndex = subItem.index;
if (labelButtons[id] && labelButtons[id][labelIndex]) {
labelButtons[id][labelIndex].onClick();
prettyPrint(id);
}
}
});
let hoveredButton = null;
chart.on("hover", async ({ id, subItem }) => {
const style = {};
const labelIndex = subItem?.type === "label" ? subItem.index : -1;
const isHoverableLabel = id !== null && labelButtons[id] && labelButtons[id][labelIndex];
const isAButtonGroup = isHoverableLabel && !!buttonGroupLabels?.[id]?.[labelIndex];
const hoverStyle = isHoverableLabel && labelButtons[id][style];
const sourceItem = itemsState.find((item) => item.id === id);
const chartElement = document.querySelector("#klchart canvas[style]");
// Always clear any hovered button first
if (hoveredButton) {
const hoveredButtonSourceItem = itemsState.find((item) => item.id === hoveredButton);
await chart.setProperties({ id: hoveredButton, t: hoveredButtonSourceItem?.t });
hoveredButton = null;
}
// clear cursor style
chartElement.classList.remove("cursor");
if (isHoverableLabel && !isAButtonGroup) {
const label = [...sourceItem.t];
label[labelIndex] = {
...label[labelIndex],
...hoverStyle,
};
await chart.setProperties({ id, t: label });
hoveredButton = id;
chartElement.classList.toggle("cursor");
} else if (isAButtonGroup) {
const label = [...sourceItem.t];
for (const index of buttonGroupLabels[id][labelIndex]) {
label[index] = {
...label[index],
...hoverStyle,
};
}
await chart.setProperties({ id, t: label });
hoveredButton = id;
chartElement.classList.toggle("cursor");
}
});
async function toggleNodeStyle(itemId) {
const interactiveNodeState = interactiveNodesState[itemId];
const nodeStyle = !interactiveNodeState ? invertedInteractiveNode : normalInteractiveNode;
// remove x and y from the styling to prevent the node snapping back to it's original position
delete nodeStyle.x;
delete nodeStyle.y;
// updtate the item state with the new toggled style
const itemIndex = itemsState.findIndex((item) => item.id === itemId);
itemsState[itemIndex] = nodeStyle;
await chart.setProperties({ id: itemId, ...nodeStyle });
interactiveNodesState[itemId] = !interactiveNodesState[itemId];
}
async function toggleLabelButtons(itemId, labelIndex, style) {
// track which buttons are toggled
const currentNodeInteractiveState = interactiveNodesState[itemId] ?? [];
currentNodeInteractiveState[labelIndex] =
currentNodeInteractiveState[labelIndex] === undefined
? true
: !currentNodeInteractiveState[labelIndex];
interactiveNodesState[itemId] = currentNodeInteractiveState;
// make sure all buttons are styled correctly depending on their toggle state
const currentStyle = itemsState.find((item) => item.id === itemId);
const originalStyle = data.items.find((item) => item.id === itemId);
const toggleStyle = { ...currentStyle, t: [...currentStyle.t] };
toggleStyle.t[labelIndex] = {
...toggleStyle.t[labelIndex],
...style,
};
// remove x and y from the styling to prevent the node snapping back to it's original position
delete toggleStyle.x;
delete toggleStyle.y;
// update the item state with the new toggled style
const itemIndex = itemsState.findIndex((item) => item.id === itemId);
itemsState[itemIndex] = toggleStyle;
currentNodeInteractiveState.forEach((toggleValue, index) => {
const originalLabelStyle = { ...originalStyle.t[index] };
const labelStyle = toggleValue ? style : originalLabelStyle;
toggleStyle.t[index] = {
...toggleStyle.t[index],
...labelStyle,
};
});
await chart.setProperties({ id: itemId, ...toggleStyle });
}
registerLabelButton("t2", 2, interactionStylePresets.interactiveNodeHover, () => {
toggleNodeStyle("t2");
});
registerLabelButtonGroup("t2", [3, 4], interactionStylePresets.interactiveNodeHover, () =>
window.open("/stylingnodes.htm#advancedlabelstyling", "_blank")
);
registerLabelButton(
"outside-buttons-rectangle",
3,
interactionStylePresets.outsideLabelActive,
() => {
toggleLabelButtons("outside-buttons-rectangle", 3, interactionStylePresets.outsideLabelHover);
}
);
registerLabelButton(
"outside-buttons-rectangle",
5,
interactionStylePresets.outsideLabelActive,
() => {
toggleLabelButtons("outside-buttons-rectangle", 5, interactionStylePresets.outsideLabelHover);
}
);
registerLabelButton(
"outside-buttons-rectangle",
7,
interactionStylePresets.outsideLabelActive,
() => {
toggleLabelButtons("outside-buttons-rectangle", 7, interactionStylePresets.outsideLabelHover);
}
);
registerLabelButton(
"outside-buttons-circle",
3,
interactionStylePresets.outsideLabelActive,
() => {
toggleLabelButtons("outside-buttons-circle", 3, interactionStylePresets.outsideLabelHover);
}
);
registerLabelButton(
"outside-buttons-circle",
4,
interactionStylePresets.outsideLabelActive,
() => {
toggleLabelButtons("outside-buttons-circle", 4, interactionStylePresets.outsideLabelHover);
}
);
registerLabelButton(
"outside-buttons-circle",
5,
interactionStylePresets.outsideLabelActive,
() => {
toggleLabelButtons("outside-buttons-circle", 5, interactionStylePresets.outsideLabelHover);
}
);
}
async function startKeyLines() {
const options = {
logo: { u: "/images/Logo.png" },
handMode: true,
selectionColour: "#FF9933",
iconFontFamily: "Font Awesome 5 Free",
overview: { icon: false },
navigation: { shown: false },
hover: 0,
};
chart = await KeyLines.create({ container: "klchart", options });
await chart.load(data);
await chart.zoom("fit");
initializeInteractions();
}
function loadFontsAndStart() {
document.fonts.ready
.then(() =>
Promise.all([
document.fonts.load('1em "Font Awesome 5 Free"'),
document.fonts.load('1em "Raleway"'),
document.fonts.load('1em "Montserrat"'),
document.fonts.load('1em "Varela Round"'),
document.fonts.load('1em "Material Icons"'),
])
)
.then(startKeyLines);
}
window.addEventListener("DOMContentLoaded", loadFontsAndStart); import KeyLines from "keylines";
export const interactionStylePresets = {
outsideLabelActive: { fbc: "#d1fae5" },
outsideLabelHover: { fbc: "#6ee7b7" },
interactiveNodeHover: { fbc: "#9A9B9B" },
};
const lineSVG = `data:image/svg+xml;base64,${btoa(
`<svg xmlns="http://www.w3.org/2000/svg" fill="#e2e8f0" width="256px" height="5px">
<g id="SVGRepo_bgCarrier" stroke-width="0">
</g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round">
</g>
<g id="SVGRepo_iconCarrier">
<rect width="256" height="5" />
</g>
</svg>`
)}`;
function makeProfileCardNode(id, x, y) {
return {
type: "node",
id,
x,
y,
c: "#f1f5f9",
w: 300,
h: "auto",
borderRadius: "10 10 6 6",
t: [
{
fi: { t: "fas fa-user" },
fs: 100,
fc: "rgb(81, 136, 168)",
fbc: "#f1f5f9",
b: "rgb(0, 85, 135)",
bw: 5,
borderRadius: 60,
minHeight: 100,
minWidth: 100,
margin: "-50 0 0 0",
position: {
vertical: "top",
},
},
{
t: "John Doe",
fs: 30,
fb: true,
fc: "rgb(0, 85, 135)",
fbc: "transparent",
margin: "10 0 0 0",
},
{
fi: { t: "fas fa-envelope" },
fs: 12,
fc: "rgb(81, 136, 168)",
fbc: "transparent",
margin: "10 0 0 0",
},
{
t: "[email protected]",
fs: 10,
fc: "rgb(81, 136, 168)",
fbc: "transparent",
margin: "10 0 0 0",
position: {
vertical: "inherit",
},
},
{
fi: { t: "fas fa-code" },
fs: 12,
fc: "rgb(81, 136, 168)",
fbc: "transparent",
margin: "10 0 0 0",
},
{
t: "Software Developer",
fs: 10,
margin: "10 0 0 0",
fc: "black",
fbc: "transparent",
position: {
vertical: "inherit",
},
},
{
t: "[email protected]",
fs: 10,
fc: "white",
fbc: "rgb(81, 136, 168)",
borderRadius: "0 0 6 6",
margin: "10 0 0 0",
padding: "10 0 10 0",
minWidth: 300,
position: {
vertical: "bottom",
},
},
],
};
}
function makeBusinessProcessNode(id, x, y) {
return {
type: "node",
id,
x,
y,
c: "#ecfdf5",
w: 400,
h: 120,
b: "#e5e5e5",
bw: 2,
borderRadius: 10,
t: [
{
t: "Business Process 1",
fs: 26,
fc: "#334155",
fbc: "transparent",
margin: {
top: 8,
right: 0,
bottom: 0,
left: 8,
},
position: {
vertical: "top",
horizontal: "left",
},
},
{
t: "2140.0",
fs: 26,
fc: "#334155",
fbc: "transparent",
textAlignment: {
vertical: "bottom",
},
margin: {
top: 0,
right: 0,
bottom: 20,
left: 8,
},
position: {
vertical: "bottom",
horizontal: "left",
},
},
{
t: "GBP",
fs: 20,
fc: "#334155",
fbc: "transparent",
textAlignment: {
vertical: "bottom",
},
minHeight: 36,
margin: {
top: 0,
right: 0,
bottom: 21,
left: 0,
},
position: {
vertical: "bottom",
},
},
{
fi: {
t: "fas fa-caret-up",
c: "#10b981",
},
fs: 36,
fbc: "transparent",
textAlignment: {
vertical: "bottom",
},
minHeight: 36,
margin: {
top: 0,
right: 2,
bottom: 15,
left: 0,
},
position: {
vertical: "bottom",
horizontal: "right",
},
},
{
t: "55.12%",
fs: 20,
fc: "#10b981",
fbc: "transparent",
textAlignment: {
vertical: "bottom",
},
position: {
vertical: "inherit",
},
margin: {
top: 0,
right: 8,
bottom: 20,
left: 0,
},
minHeight: 36,
},
{
fs: 0,
fbc: "#e5e5e5",
minWidth: 402,
minHeight: 18,
borderRadius: [0, 0, 9, 9],
position: {
vertical: 103,
horizontal: "centre",
},
padding: 0,
},
{
minWidth: 394,
fs: 10,
borderRadius: [0, 0, 10, 10],
fbc: "#f1f5f9",
position: {
vertical: "bottom",
horizontal: "left",
},
margin: 1,
},
{
borderRadius: [0, 0, 0, 10],
margin: {
top: 1,
right: 1,
bottom: 1,
left: 1,
},
fs: 10,
fbc: "#10b981",
minWidth: 230.5,
position: {
horizontal: "left",
vertical: "bottom",
},
},
{
fbc: "#f1f5f9",
minWidth: 40,
minHeight: 60,
position: { vertical: "middle", horizontal: -46 },
borderRadius: [5, 0, 0, 5],
bw: 2,
b: "#e5e5e5",
fs: 26,
fi: {
t: "fas fa-people-arrows",
c: "#334155",
},
},
],
};
}
function makeShadowCircleNode(id, x, y, colour, icon, text) {
return {
type: "node",
id,
x,
y,
c: colour,
b: "#283618",
bw: 2,
e: 1.5,
ff: "Varela Round",
ha0: {
c: "rgba(220,220,220,1)",
r: 29,
w: 1,
},
ha1: {
c: "rgba(220,220,220,0.8)",
r: 30,
w: 1,
},
ha2: {
c: "rgba(220,220,220,0.6)",
r: 31,
w: 1,
},
ha3: {
c: "rgba(220,220,220,0.4)",
r: 32,
w: 1,
},
ha4: {
c: "rgba(220,220,220,0.2)",
r: 33,
w: 1,
},
t: [
{
fi: { t: icon, ff: "Material Icons" },
fs: 30,
fc: "#283618",
fbc: "rgba(0, 0, 0, 0)",
padding: {
top: 6,
right: 2,
bottom: 0,
left: 2,
},
position: { vertical: "top" },
},
{
t: text,
fs: 10,
fb: true,
fc: "#283618",
fbc: "rgba(0, 0, 0, 0)",
},
],
};
}
function makeMaterialIconLabel(icon, fs, colour) {
return {
position: {
horizontal: "centre",
vertical: "middle",
},
ff: "Material Icons",
fs: fs,
fc: colour,
fbc: "transparent",
fi: {
t: icon,
},
padding: {
top: 5,
right: 2,
bottom: 0,
left: 2,
},
};
}
function makeInteractiveNode(id, x, y, backgroundColour, accentColour) {
return {
type: "node",
id,
x,
y,
b: accentColour,
borderRadius: [0, 10, 20, 10],
c: backgroundColour,
w: 305,
h: 85,
t: [
{
fbc: "transparent",
fc: accentColour,
fi: { t: "fas fa-desktop" },
position: {
horizontal: "left",
vertical: "middle",
},
fs: 35,
margin: {
left: 17.5,
},
},
{
fbc: "transparent",
fc: accentColour,
fb: true,
fs: 16,
padding: "0 10 0 0",
position: {
horizontal: 70,
vertical: 15,
},
t: "Interactive Node",
textAlignment: {
horizontal: "left",
},
},
{
fbc: accentColour,
fc: backgroundColour,
borderRadius: 10,
fb: true,
margin: "10 0",
minWidth: 60,
padding: {
top: 8,
right: 10,
bottom: 6,
left: 10,
},
position: {
horizontal: 70,
},
t: "Invert Style",
},
{
fb: true,
fc: backgroundColour,
fbc: accentColour,
fs: 14,
margin: {
top: 10,
right: 10,
bottom: 0,
left: 10,
},
borderRadius: [10, 0, 0, 10],
padding: {
top: 9,
right: 10,
bottom: 9.75,
left: 10,
},
position: {
vertical: "inherit",
},
fi: { t: "fas fa-external-link-alt" },
},
{
fbc: accentColour,
fc: backgroundColour,
borderRadius: [0, 10, 10, 0],
fb: true,
margin: {
top: 10,
right: 0,
bottom: 0,
left: 30,
},
minWidth: 60,
padding: {
top: 8,
right: 10,
bottom: 6,
left: 1,
},
position: {
horizontal: 170,
vertical: "inherit",
},
t: "Go to Docs ",
},
],
};
}
export const normalInteractiveNode = makeInteractiveNode("t2", 425, 100, "#f4f3ee", "#3d405b");
export const invertedInteractiveNode = makeInteractiveNode("t2", 425, 100, "#3d405b", "#f4f3ee");
export const data = {
type: "LinkChart",
items: [
{
id: "t1-a",
type: "node",
c: "#A485D5",
w: 100,
h: 150,
x: -475,
y: -145,
bw: 3,
b: "#69738C",
borderRadius: 10,
t: [
{
fi: { t: "fas fa-server" },
fs: 50,
fbc: "transparent",
fc: "white",
position: { vertical: 24 },
},
{
t: "Rack A",
fs: 15,
fbc: "transparent",
fc: "white",
fb: true,
margin: "10 0 0 0",
},
{
t: "OK",
fs: 11,
fbc: "transparent",
fc: "white",
padding: "0 20",
margin: "5 0 0 0",
},
{
fs: 0,
fbc: "#69738C",
borderRadius: "0 0 8.5 8.5",
margin: 0,
padding: 0,
minWidth: 103,
minHeight: 21.5,
position: {
horizontal: -1.5,
vertical: 130,
},
},
{
fs: 0,
fbc: "#FACA16",
margin: 0,
padding: 0,
minWidth: 60,
minHeight: 17,
position: {
horizontal: 0,
vertical: 133,
},
borderRadius: "0 0 0 7",
},
],
},
{
id: "t1-b",
type: "node",
c: "#A485D5",
w: 100,
h: 150,
x: -350,
y: -145,
bw: 3,
b: "#69738C",
borderRadius: 10,
t: [
{
fi: { t: "fas fa-server" },
fs: 50,
fbc: "transparent",
fc: "white",
position: { vertical: 24 },
},
{
t: "Rack B",
fs: 15,
fbc: "transparent",
fc: "white",
fb: true,
margin: "10 0 0 0",
},
{
t: "OK",
fs: 11,
fbc: "transparent",
fc: "white",
padding: "0 20",
margin: "5 0 0 0",
},
{
fs: 0,
fbc: "#69738C",
borderRadius: "0 0 8.5 8.5",
margin: 0,
padding: 0,
minWidth: 103,
minHeight: 21.5,
position: {
horizontal: -1.5,
vertical: 130,
},
},
{
fs: 0,
fbc: "#FF3C38",
margin: 0,
padding: 0,
minWidth: 80,
minHeight: 17,
position: {
horizontal: 0,
vertical: 133,
},
borderRadius: "0 0 0 7",
},
],
},
{
id: "t1-c",
type: "node",
c: "#61A899",
w: 100,
h: 150,
x: -597,
y: -145,
bw: 3,
b: "#69738C",
borderRadius: 10,
t: [
{
fi: { t: "fas fa-hdd" },
fs: 50,
fbc: "transparent",
fc: "white",
position: { vertical: 24 },
},
{
t: "Blade C",
fs: 15,
fbc: "transparent",
fc: "white",
fb: true,
margin: "10 0 0 0",
},
{
t: "High CPU usage",
fs: 11,
fbc: "transparent",
fc: "white",
padding: "0 20",
margin: "5 0 0 0",
},
{
fs: 0,
fbc: "#69738C",
borderRadius: "0 0 8.5 8.5",
margin: 0,
padding: 0,
minWidth: 103,
minHeight: 21.5,
position: {
horizontal: -1.5,
vertical: 130,
},
},
{
fs: 0,
fbc: "#65B540",
margin: 0,
padding: 0,
minWidth: 30,
minHeight: 17,
position: {
horizontal: 0,
vertical: 133,
},
borderRadius: "0 0 0 7",
},
],
},
normalInteractiveNode,
{
id: "j1-rectangle",
type: "node",
c: "#34d399",
ff: "Montserrat",
w: 230,
h: 70,
x: -105,
y: -461,
minHeight: 80,
t: [
{
fi: { t: "fas fa-random" },
fs: 35,
fc: "#34d399",
fbc: "#404347",
minHeight: 55,
margin: "0 0 0 7.5",
padding: {
top: 2,
right: 2,
bottom: 0,
left: 10,
},
},
{
t: "Generate Data",
fs: "auto",
fb: true,
fc: "white",
fbc: "#404347",
minHeight: 55,
margin: {
top: 0,
right: 7.5,
bottom: 0,
left: 0,
},
padding: {
top: 2,
right: 13,
bottom: 0,
left: 13,
},
position: { vertical: "inherit" },
},
],
},
{
id: "j2-rectangle",
type: "node",
c: "#FFE642",
ff: "Montserrat",
w: 230,
h: 70,
x: -105,
y: -355,
minHeight: 80,
t: [
{
fi: { t: "fas fa-database" },
fs: 35,
fc: "#FFE642",
fbc: "#404347",
minHeight: 55,
margin: "0 0 0 7.5",
padding: {
top: 2,
right: 2,
bottom: 0,
left: 10,
},
},
{
t: "Open Database",
fs: "auto",
fb: true,
fc: "white",
fbc: "#404347",
minHeight: 55,
margin: {
top: 0,
right: 7.5,
bottom: 0,
left: 0,
},
padding: {
top: 2,
right: 13,
bottom: 0,
left: 13,
},
position: { vertical: "inherit" },
},
{
t: "Unavailable",
fs: 12,
fc: "white",
fbc: "#404347",
bw: 3,
b: "#FFE642",
borderRadius: 20,
margin: { bottom: -20, left: -60 },
padding: {
top: 8,
right: 8,
bottom: 6,
left: 8,
},
position: "ne",
},
],
},
{
id: "j3-rectangle",
type: "node",
c: "#fb7185",
ff: "Montserrat",
w: 230,
h: 70,
x: -105,
y: -240,
minHeight: 80,
t: [
{
fi: { t: "fas fa-bug" },
fs: 35,
fc: "#fb7185",
fbc: "#404347",
minHeight: 55,
margin: "0 0 0 7.5",
padding: {
top: 2,
right: 2,
bottom: 0,
left: 10,
},
},
{
t: "Debug Console",
fs: "auto",
fb: true,
fc: "white",
fbc: "#404347",
minHeight: 55,
margin: {
top: 0,
right: 7.5,
bottom: 0,
left: 0,
},
padding: {
top: 2,
right: 13,
bottom: 0,
left: 13,
},
position: { vertical: "inherit" },
},
{
t: "Unavailable",
fs: 12,
fc: "white",
fbc: "#404347",
bw: 3,
b: "#fb7185",
borderRadius: 20,
margin: { bottom: -20, left: -60 },
padding: {
top: 8,
right: 8,
bottom: 6,
left: 8,
},
position: "ne",
},
],
},
makeShadowCircleNode("j4-circle", 247, -100, "#fefae0", "local_florist", "Bloom"),
makeShadowCircleNode("j5-circle", 120, -122, "#f4f3ee", "air", "Blow"),
makeShadowCircleNode("j6-circle", 203, -222, "#cd4631", "local_fire_department", "Burn"),
makeProfileCardNode("j7-profile-card", -500, -400),
{
id: "c1-circle",
type: "node",
sh: "circle",
c: "rgba(0,0,0,0)",
e: 1.7,
x: -40,
y: -25,
t: [
makeMaterialIconLabel("circle", 75, "#0f2e18"),
makeMaterialIconLabel("circle", 70, "#FFF"),
makeMaterialIconLabel("circle", 65, "#0f2e18"),
makeMaterialIconLabel("circle", 60, "#FFF"),
makeMaterialIconLabel("circle", 55, "#0f2e18"),
{
...makeMaterialIconLabel("flight", 30, "#FFF"),
padding: { top: 0, right: 0, bottom: 0, left: 1 },
},
],
},
{
id: "c1-hexagon",
type: "node",
sh: "box",
c: "rgba(0,0,0,0)",
e: 1.7,
x: -105,
y: 100,
t: [
makeMaterialIconLabel("hexagon", 75, "#001845"),
makeMaterialIconLabel("hexagon", 70, "#FFF"),
makeMaterialIconLabel("hexagon", 65, "#001845"),
makeMaterialIconLabel("hexagon", 60, "#FFF"),
makeMaterialIconLabel("hexagon", 55, "#001845"),
makeMaterialIconLabel("place", 30, "#FFF"),
],
},
{
id: "c1-square",
type: "node",
sh: "box",
c: "rgba(0,0,0,0)",
e: 1.7,
x: 45,
y: 100,
t: [
makeMaterialIconLabel("square", 75, "#540b0e"),
makeMaterialIconLabel("square", 70, "#FFF"),
makeMaterialIconLabel("square", 65, "#540b0e"),
makeMaterialIconLabel("square", 60, "#FFF"),
makeMaterialIconLabel("square", 55, "#540b0e"),
makeMaterialIconLabel("question_answer", 30, "#FFF"),
],
},
makeBusinessProcessNode("c1", 380, -434),
{
id: "node_Emanuela Cooper",
type: "node",
w: "auto",
h: "auto",
c: "#734b6d",
b: "white",
bw: 1,
borderRadius: 10,
t: [
{
u: `/im/people/Person3.png`,
position: { horizontal: "left" },
margin: 10,
},
{
t: "Emanuela Cooper",
position: { vertical: "inherit" },
margin: { right: 10 },
fbc: "transparent",
fc: "#faf5ff",
},
],
x: 480,
y: -250,
g: [
{
p: "ne",
fi: {
t: "fas fa-plus",
ff: "Font Awesome 5 Free",
c: "white",
},
b: "transparent",
c: "rgba(183, 92, 170, 1)",
e: 1.2,
},
{
fi: {
t: "fas fa-expand-arrows-alt",
c: "white",
ff: "Font Awesome 5 Free",
},
c: "#513BC4",
b: "transparent",
p: "se",
e: 1.2,
},
],
},
{
id: "node_Vito Morello",
type: "node",
w: "auto",
h: 35,
c: "#734b6d",
b: "white",
bw: 1,
borderRadius: 10,
t: [
{
t: "Vito Morello",
margin: { left: 10 },
position: { horizontal: "left" },
fbc: "transparent",
fc: "#faf5ff",
},
{
u: `/im/people/Person9.png`,
position: { vertical: "inherit" },
margin: {
left: 10,
right: 20,
},
},
],
x: 480,
y: -145,
g: [
{
p: "ne",
fi: {
t: "fas fa-plus",
ff: "Font Awesome 5 Free",
c: "white",
},
b: "transparent",
c: "rgba(183, 92, 170, 1)",
e: 1.2,
},
{
fi: {
t: "fas fa-expand-arrows-alt",
c: "white",
ff: "Font Awesome 5 Free",
},
c: "#513BC4",
b: "transparent",
p: "se",
e: 1.2,
},
],
},
{
id: "people",
type: "node",
w: "auto",
h: 50,
c: "#734b6d",
b: "white",
bw: 1,
borderRadius: 10,
t: [
{
t: "Team",
margin: {
left: 10,
},
position: {
horizontal: "left",
},
fbc: "transparent",
fc: "#faf5ff",
},
{
u: `/im/people/Person2.png`,
position: {
vertical: "inherit",
},
maxWidth: 30,
maxHeight: 30,
margin: {
left: 10,
},
},
{
u: `/im/people/Person13.png`,
position: {
vertical: "inherit",
},
maxWidth: 30,
maxHeight: 30,
margin: {
left: -5,
},
},
{
u: `/im/people/Person8.png`,
position: {
vertical: "inherit",
},
maxWidth: 30,
maxHeight: 30,
margin: {
left: -5,
},
},
{
u: `/im/people/Person5.png`,
position: {
vertical: "inherit",
},
maxWidth: 30,
maxHeight: 30,
margin: {
left: -5,
},
},
{
fi: { t: "fas fa-ellipsis-h", c: "#334155" },
position: {
vertical: "inherit",
},
fs: 20,
minWidth: 30,
minHeight: 29.5,
borderRadius: 180,
fbc: "#f8fafc",
padding: [1, 0, 0, 0],
margin: {
left: -5,
right: 10,
},
},
],
x: 480,
y: -55,
},
{
id: "outside-buttons-rectangle",
type: "node",
x: -597,
y: 80,
c: "#f3f4f6",
w: 100,
h: 130,
borderRadius: 10,
bw: 1,
b: "rgba(229, 231, 235, 0.8)",
t: [
{
fi: { t: "fas fa-file-invoice", c: "#0d9488" },
fbc: "rgba(0,0,0,0)",
fs: 40,
position: { horizontal: "centre", vertical: "top" },
margin: {
top: 15,
bottom: 10,
},
},
{
t: "Insurance Policy",
fbc: "rgba(0,0,0,0)",
fc: "#334155",
textWrap: "normal",
},
{
t: "id: 842 921",
fbc: "rgba(0,0,0,0)",
fc: "#64748b",
textWrap: "normal",
fs: 12,
margin: { top: 10, bottom: 10 },
},
// side buttons
{
fi: { t: "fas fa-check", c: "#0f766e" },
fbc: "#f3f4f6",
fs: 18,
minHeight: 30,
minWidth: 30,
position: { horizontal: 110, vertical: "top" },
borderRadius: [5, 5, 0, 0],
},
{
maxHeight: 1,
maxWidth: 34,
fbc: "red",
u: lineSVG,
},
{
fi: { t: "fas fa-bell-slash", c: "#0f766e" },
fbc: "#f3f4f6",
fs: 18,
minHeight: 30,
minWidth: 30,
},
{
maxHeight: 1,
maxWidth: 34,
fbc: "red",
u: lineSVG,
},
{
fi: { t: "fas fa-eye-slash", c: "#0f766e" },
fbc: "#f3f4f6",
fs: 18,
minHeight: 30,
minWidth: 30,
borderRadius: [0, 0, 5, 5],
},
],
},
{
id: "outside-buttons-circle",
type: "node",
x: -400,
y: 80,
c: "#f3f4f6",
w: 130,
h: 130,
borderRadius: 180,
bw: 1,
b: "rgba(229, 231, 235, 0.8)",
t: [
{
fi: { t: "fas fa-file-invoice", c: "#0d9488" },
fbc: "rgba(0,0,0,0)",
fs: 40,
position: { horizontal: "centre", vertical: "top" },
margin: {
top: 15,
bottom: 10,
},
},
{
t: "Insurance Policy",
fbc: "rgba(0,0,0,0)",
fc: "#334155",
textWrap: "normal",
},
{
t: "id: 842 921",
fbc: "rgba(0,0,0,0)",
fc: "#64748b",
textWrap: "normal",
fs: 12,
margin: { top: 10, bottom: 10 },
},
// side buttons
{
fi: { t: "fas fa-check", c: "#0f766e" },
fbc: "#f3f4f6",
fs: 18,
minHeight: 32,
minWidth: 32,
position: { horizontal: 135, vertical: 10 },
borderRadius: 180,
margin: 2.5,
padding: 0,
},
{
fi: { t: "fas fa-bell-slash", c: "#0f766e" },
fbc: "#f3f4f6",
fs: 18,
minHeight: 32,
minWidth: 32,
borderRadius: 180,
margin: 2.5,
padding: 0,
},
{
fi: { t: "fas fa-eye-slash", c: "#0f766e" },
fbc: "#f3f4f6",
fs: 18,
minHeight: 32,
minWidth: 32,
borderRadius: 180,
margin: 2.5,
padding: 0,
},
],
},
],
}; <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Advanced Node Styles</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"
/>
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css2?family=Raleway&family=Montserrat&family=Varela+Round"
/>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div id="klchart" class="klchart"></div>
<script type="module" src="./code.js"></script>
</body>
</html> @import url("https://fonts.googleapis.com/icon?family=Material+Icons");
/* Enable cursor overriding while hovering the chart */
.cursor {
cursor: pointer !important;
}