JointJS - Metro with ports v3.6

by Roman Bruckner

HTML

<html>

  <head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.6.3/joint.css" />
  </head>

  <body>
    <!-- content -->
    <div id="paper"></div>

    <!-- dependencies -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.0/backbone.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.6.3/joint.js"></script>

  </body>

</html>

JavaScript

const {
    dia,
    shapes: defaultShapes,
  } = joint;

  const shapes = {
    ...defaultShapes,
  };

  const graph = new dia.Graph({}, {
    cellNamespace: shapes
  });

  const GRID = 10;
  const WIDTH = 10;
    const HEIGHT = 5;
    const PORT = 2;

  const paper = new dia.Paper({
    el: document.getElementById('paper'),
    width: 800,
    height: 600,
    model: graph,
    cellViewNamespace: shapes,
    async: true,
    gridSize: GRID
  });

  const el1 = new shapes.standard.Rectangle({
    size: {
      width: WIDTH * 2 * GRID,
      height: HEIGHT * 2 * GRID
    },
    position: {
      x: 400,
      y: 50
    },
    ports: {
        groups: {
            in: {
                position: {
                    name: 'top',
                },
                attrs: {
                    circle: {
                        r: GRID / 2 * PORT,
                    },
                },
            },
            out: {
                position: {
                    name: 'bottom',
                },
                attrs: {
                    circle: {
                        r: GRID / 2 * PORT,
                    }
                }
            }
        },
        items: [{
            group: 'in',
            id: 'in',
        }, {
            group: 'out',
            id: 'out',
        }]
    }
  });

const el2 = el1.clone();
el2.position(200, 300);
const el3 = el1.clone();
el3.position(600, 300);
const el4 = el1.clone();
el4.position(400, 300);


const link1 = new shapes.standard.Link({
    router: {
        name: 'metro',
        args: {
            step: GRID,
        }
    }
});

link1.source(el1, { port: 'out' });
link1.target(el2, { port: 'in' });

const link2 = link1.clone();
link2.source(el1, { port: 'out' });
link2.target(el3, { port: 'in' });

const link3 = link1.clone();
link3.source(el1, { port: 'out' });
link3.target(el4, { port: 'in' });

graph.addCells([el1, el2, el3, el4, link1, link2, link3]);