Appearance
Text on edge extremities 
This example shows how to display texts at the edges' extremities. It uses the canvas layer API to do so.
ts
import Ogma, { Point, Edge } from '@linkurious/ogma';
const ogma = new Ogma({
  container: 'graph-container'
});
ogma.styles.addEdgeRule({ shape: { head: 'arrow' } });
function distance(vec1: Point, vec2: Point) {
  const dx = vec2.x - vec1.x;
  const dy = vec2.y - vec1.y;
  return Math.sqrt(dx * dx + dy * dy);
}
const SOURCE_SIDE = 0;
const TARGET_SIDE = 1;
function displayOnEdge({
  edge,
  ctx,
  drawFunction,
  rotateText = true,
  // translation from the center of the edgeExtremity
  distToExtremity = 12,
  // margin between the edge and the text
  margin = 2,
  side = SOURCE_SIDE
}: {
  edge: Edge;
  ctx: CanvasRenderingContext2D;
  drawFunction: (args: { ctx: CanvasRenderingContext2D; edge: Edge }) => void;
  rotateText?: boolean;
  distToExtremity?: number;
  margin?: number;
  side?: typeof SOURCE_SIDE | typeof TARGET_SIDE;
}) {
  // compute the interpolation ratio that represents distToExtremity on the edge.
  const [source, target] = edge
    .getExtremities()
    .map(node => node.getPosition());
  const dist = distance(source, target);
  let t = distToExtremity / dist;
  // if we are on TARGET_SIDE, reverse the interpolation ratio
  if (side === TARGET_SIDE) {
    t = 1 - t;
  }
  // get the point, tangent and normal vectors where we want to display the text
  const point = Ogma.geometry.getPointOnEdge(edge, t);
  const tangent = Ogma.geometry.getTangentOnEdge(edge, t);
  // compute the rotation angle for the text
  let angle = Math.atan2(tangent.y, tangent.x);
  if (angle <= -Math.PI / 2 || angle >= Math.PI / 2) {
    angle += Math.PI;
  }
  ctx.save();
  ctx.beginPath();
  // translate the context to the text center
  ctx.translate(point.x, point.y);
  // rotate it so it's parrallel to the edge
  if (rotateText) {
    ctx.rotate(angle);
  }
  // translate it so there is margin between the edge and the text
  ctx.translate(0, margin);
  // draw the text
  drawFunction({ ctx, edge });
  ctx.stroke();
  ctx.restore();
}
function draw(ctx: CanvasRenderingContext2D) {
  ctx.font = '2px sans-serif';
  ogma.getEdges().forEach(edge => {
    // display on edge will give you a ctx rotated and translated
    // to the right place
    displayOnEdge({
      edge,
      ctx,
      // draw a text at the begining of the edge
      drawFunction: ({ edge, ctx }) => {
        const text = edge.getData('sourceText');
        const w2 = ctx.measureText(text).width / 2;
        ctx.fillText(text, -w2, 0);
      }
    });
    displayOnEdge({
      edge,
      ctx,
      side: TARGET_SIDE,
      // draw a text at the end of the edge
      drawFunction: ({ edge, ctx }) => {
        const text = edge.getData('targetText');
        const w2 = ctx.measureText(text).width / 2;
        ctx.fillText(text, -w2, 0);
      }
    });
  });
}
const graph = {
  nodes: [{ id: 0 }, { id: 1 }],
  edges: [
    {
      source: 0,
      target: 1,
      data: { sourceText: 'Source 0', targetText: 'Target 0' }
    },
    {
      source: 1,
      target: 0,
      data: { sourceText: 'Source 1', targetText: 'Target 1' }
    },
    {
      source: 1,
      target: 0,
      data: { sourceText: 'Source 2', targetText: 'Target 2' }
    },
    {
      source: 1,
      target: 0,
      data: { sourceText: 'Source 3', targetText: 'Target 3' }
    },
    {
      source: 1,
      target: 0,
      data: { sourceText: 'Source 4', targetText: 'Target 4' }
    }
  ]
};
// setup the graph
await ogma.setGraph(graph);
await ogma.layouts.force({ locate: true });
// create the layer
const edgeTextLayer = ogma.layers.addCanvasLayer(draw);
// hide and show on draging
ogma.events
  .on('nodesDragStart', () => {
    edgeTextLayer.hide();
  })
  .on('nodesDragEnd', () => {
    edgeTextLayer.show();
  });html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <link type="text/css" rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <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;
}
.brand {
  background-color: rgba(255, 255, 255, 0.7);
  font-size: 10px;
  padding: 5px;
  margin: 0;
  font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
}