Appearance
Diagrams
This example shows how you can dynamically illustrate the data flow in a neural network. It combines area annotations with zoomable node annotations. You can also click on the nodes to show, hide or fade their overlays.
ts
import Ogma from '@linkurious/ogma';
import './styles.css';
const ogma = new Ogma({
container: 'graph-container',
options: {
backgroundColor: null
}
});
ogma.styles.addNodeRule({
radius: 15
});
const graph = await Ogma.parse.jsonFromUrl('data-flow.json');
await ogma.addGraph(graph);
await ogma.layouts.hierarchical({
direction: 'LR',
locate: true,
levelDistance: 300,
nodeDistance: 110
});
const overlays = ogma.getNodes().map((node, i) => {
const pos = node.getPosition();
const width = 200;
const height = 100;
const data = node.getData();
// link the overlay with the node for updates
node.setData('overlayId', i);
const color = node.getAttribute('color');
return ogma.layers
.addOverlay({
element: `<div class="tooltip right data-card">
<div class="arrow"></div>
<div class="tooltip-body">
<div class="wrapper" style="border-color: ${color}">
<h3>${
data.properties.name ||
data.properties.label ||
data.properties.full_name
}</h3>
</div>
</div>
</div>`,
position: { x: pos.x + 15, y: pos.y - height / 2 },
size: { width: `${width}px`, height: `${height}px` }
})
.moveToTop();
});
// disable node dragging
await ogma.getNodes().setAttribute('draggable', false);
const FADED = 0.3;
const SHOWN = 1;
// show/hide overlays on click
ogma.events
.on('click', ({ target }) => {
if (target && target.isNode) {
const overlay = overlays[target.getData('overlayId')];
// show/hide for patterns
if (target.getData('type') === 'pattern') {
if (overlay.isHidden()) {
target.setAttribute('icon.content', null);
return overlay.show();
}
target.setAttribute('icon.content', '+');
return overlay.hide();
}
// fade/reveal for the others
overlay.setOpacity(overlay.getOpacity() === FADED ? SHOWN : FADED);
}
})
// bring tooltips to top on mouseover
.on('mouseover', ({ target }) => {
if (target && target.isNode) {
const overlay = overlays[target.getData('overlayId')];
overlay.moveToTop();
}
});
await ogma.view.locateGraph({
padding: {
top: -450,
left: 100,
right: 250,
bottom: -450
}
});
html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="graph-container"></div>
<script type="module" src="index.ts"></script>
</body>
</html>
css
html,
body {
margin: 0;
padding: 0;
}
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
.tooltip {
max-width: 240px;
max-height: 280px;
background-color: #fff;
border: 1px solid #999;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
border-radius: 6px;
cursor: auto;
font-family: Arial;
font-size: 12px;
z-index: 1000;
}
.tooltip .icon {
font-family: Font Awesome 5 Free;
}
.tooltip-header {
font-variant: small-caps;
font-size: 120%;
color: #000;
border-bottom: 1px solid #999;
padding: 10px;
}
.tooltip-body {
padding: 10px;
max-width: inherit;
overflow-y: auto;
overflow-x: hidden;
box-sizing: border-box;
height: 100%;
}
.tooltip-body th {
color: #999;
text-align: left;
}
.tooltip-footer {
padding: 10px;
border-top: 1px solid #999;
}
.tooltip > .arrow {
border-width: 10px;
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
.tooltip.top {
margin-top: -12px;
}
.tooltip.top > .arrow {
left: 50%;
bottom: -10px;
margin-left: -10px;
border-top-color: #999;
border-bottom-width: 0;
}
.tooltip.bottom {
margin-top: 12px;
}
.tooltip.bottom > .arrow {
left: 50%;
top: -10px;
margin-left: -10px;
border-bottom-color: #999;
border-top-width: 0;
}
.tooltip.left {
margin-left: -12px;
}
.tooltip.left > .arrow {
top: 50%;
right: -10px;
margin-top: -10px;
border-left-color: #999;
border-right-width: 0;
}
.tooltip.right > .arrow {
top: 50%;
left: -10px;
margin-top: -10px;
border-right-color: #999;
border-left-width: 0;
}
.tooltip-body .wrapper {
border-width: 0 0 0 5px;
border-style: solid;
padding: 5px;
}
.tooltip h3 {
color: #444;
}
.tooltip:hover h3 {
color: #222;
cursor: pointer;
text-decoration: underline;
}
json
{
"nodes": [
{
"id": 0,
"attributes": {
"x": 2995,
"y": 300,
"color": "#2ca02c",
"radius": 5,
"shape": "circle",
"text": "Customer Portfolio"
},
"data": {
"categories": [
"Concept"
],
"properties": {
"name": "Customer Portfolio",
"definition": "A grouping of financial assets such as stocks, bonds and cash equivalents, as well as their mutual, exchange-traded and closed-fund counterparts. Portfolios are held directly by investors and/or managed by financial professionals.",
"id": 4
}
},
"x": 421.66666666666674,
"y": 0,
"r": 8.889887252841921,
"layer": 0,
"sink": false
},
{
"id": 1,
"attributes": {
"x": 2667.5,
"y": 200,
"color": "#ff7f0e",
"radius": 5,
"shape": "circle",
"text": "Customer"
},
"data": {
"categories": [
"Subject Area"
],
"properties": {
"name": "Customer"
}
},
"x": 337.33333333333337,
"y": 99.47145877378435,
"r": 7.015674871145073,
"sink": false
},
{
"id": 2,
"attributes": {
"x": 3127.5,
"y": 250,
"color": "#1f77b4",
"radius": 5,
"shape": "circle",
"text": "Portfolio Code"
},
"data": {
"categories": [
"DataElement"
],
"properties": {
"id": 9,
"label": "Portfolio Code"
}
},
"x": 506,
"y": 99.47145877378435,
"r": 5.461372976784961,
"sink": false
},
{
"id": 3,
"attributes": {
"x": 2867.5,
"y": 250,
"color": "#1f77b4",
"radius": 5,
"shape": "circle",
"text": "Portfolio Short Name"
},
"data": {
"categories": [
"DataElement"
],
"properties": {
"id": 8,
"label": "Portfolio Short Name"
}
},
"x": 463.8333333333333,
"y": 99.47145877378435,
"r": 10.645027362934385,
"sink": false
},
{
"id": 4,
"attributes": {
"x": 300,
"y": 200,
"color": "#17becf",
"radius": 5,
"shape": "circle",
"text": null
},
"data": {
"categories": [
"DataOwner"
],
"properties": {
"full_name": "David Jones",
"id": 1
}
},
"x": 674.6666666666666,
"y": 99.47145877378435,
"r": 4.378711202635261,
"sink": false
},
{
"id": 5,
"attributes": {
"x": 365,
"y": 250,
"color": "#2ca02c",
"radius": 5,
"shape": "circle",
"text": "Trader"
},
"data": {
"categories": [
"Concept"
],
"properties": {
"name": "Trader",
"definition": "An individual who engages in the transfer of financial assets in any financial market, either for themselves, or on behalf of a someone else. The main difference between a trader and an investor is the duration for which the person holds the asset. Investors tend to have a longer term time horizon, whereas traders tend to hold assets for shorter periods of time in order to capitalize on short-term trends.",
"id": 5
}
},
"x": 0,
"y": 0,
"r": 9.551798628830197,
"layer": 0,
"sink": false
},
{
"id": 6,
"attributes": {
"x": 310,
"y": 250,
"color": "#2ca02c",
"radius": 5,
"shape": "circle",
"text": "Investment"
},
"data": {
"categories": [
"Concept"
],
"properties": {
"name": "Investment",
"definition": "An asset or item that is purchased with the hope that it will generate income or appreciate in the future. In an economic sense, an investment is the purchase of goods that are not consumed today but are used in the future to create wealth. In finance, an investment is a monetary asset purchased with the idea that the asset will provide income in the future or appreciate and be sold at a higher price.",
"id": 3
}
},
"x": 759,
"y": 0,
"r": 8.277798660184793,
"layer": 0,
"sink": false
},
{
"id": 7,
"attributes": {
"x": 255,
"y": 250,
"color": "#2ca02c",
"radius": 5,
"shape": "circle",
"text": "Share Price"
},
"data": {
"categories": [
"Concept"
],
"properties": {
"name": "Share Price",
"definition": "The price of shares of a particular company at a particular time.",
"id": 2
}
},
"x": 674.6666666666667,
"y": 0,
"r": 10.763584846041306,
"layer": 0,
"sink": false
},
{
"id": 8,
"attributes": {
"x": 127.5,
"y": 250,
...