Appearance
Edge badges
This example shows you how to render edge badges on the edges using layers. Note how the rendering function skips the icons that are outside of the viewport.
ts
import Ogma from '@linkurious/ogma';
const ogma = new Ogma({
container: 'graph-container',
graph: {
nodes: [{ id: 'us' }, { id: 'de' }, { id: 'fr' }],
edges: [
{ source: 'us', target: 'de' },
{ source: 'de', target: 'fr' },
{ source: 'fr', target: 'us' }
]
},
options: {
interactions: {
zoom: { maxValue: () => Infinity }
}
}
});
// Icon font
const font = 'FontAwesome';
// Node and edge styles
function addStyles() {
ogma.styles.addRule({
nodeAttributes: {
radius: 9,
color: '#4d9de0',
icon: {
font: font,
content: '\uf2bd',
color: 'white'
}
},
edgeAttributes: {
width: 0.8
}
});
}
/**
* Checks if the point is inside a rectangle
*/
const isInside = (
x: number,
y: number,
minX: number,
minY: number,
maxX: number,
maxY: number
) => x >= minX && x <= maxX && y >= minY && y <= maxY;
const render = (ctx: CanvasRenderingContext2D, ogma: Ogma) => {
ogma.getEdges().forEach(edge => {
const [source, target] = edge.getExtremities().getPosition();
const cx = (source.x + target.x) / 2;
const cy = (source.y + target.y) / 2;
const tangent = Ogma.geometry.getTangentOnEdge(edge, 0.5);
let angle = Math.atan2(tangent.y, tangent.x);
// angle correction so that it's not upside down
if (angle > Math.PI / 2.0 || angle < -Math.PI / 2.0) {
angle += Math.PI;
}
// do not render if the icon is outside of the viewport + tolerance
const eps = 50;
const { x, y } = ogma.view.graphToScreenCoordinates({ x: cx, y: cy });
const { width, height } = ogma.view.getSize();
if (!isInside(x, y, 0 - eps, 0 - eps, width + eps, height + eps)) return;
// proceed to rendering
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(angle);
ctx.font = `900 5px "${font}"`;
ctx.fillStyle = '#e15554';
ctx.textBaseline = 'middle';
// note that I wasn't able to find \uF006 defined in the provided CSS
// falling back to fa-bug for demo
ctx.fillText('\uf15b', 0, 0);
ctx.restore();
});
};
await document.fonts.ready;
await addStyles();
await ogma.layouts.force({ locate: true });
// add the custom renderer
const layer = ogma.layers.addCanvasLayer(ctx => render(ctx, ogma));
ogma.events.on(['nodesDragProgress'], () => layer.refresh());
html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<link
type="text/css"
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css"
/>
<link type="text/css" rel="stylesheet" href="styles.css" />
</head>
<body>
<i class="fa fa-camera-retro fa-1x" style="color: rgba(0, 0, 0, 0)"></i>
<div id="graph-container"></div>
<script type="module" src="index.ts"></script>
</body>
</html>
css
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}