All versions of this documentation
X

Indoor maps


Open in a new window.
          <!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.js">
  </script>
  <script src="../build/ogma.min.js"></script>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/solid.min.css" rel="stylesheet">
  <style>
    html,
    body {
      margin: 0;
    }

    #graph-container {
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      position: absolute;
      margin: 0;
      overflow: hidden;
    }

    .control-bar {
      font-family: Helvetica, Arial, sans-serif;
      box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
      border-radius: 4px;
      background: white;
      padding: 5px 10px;
    }

    #controls {
      position: absolute;
      top: 10px;
      right: 10px;
      z-index: 9999;
    }

    #controls label {
      display: block;
    }

    #controls form {
      padding-top: 5px;
      line-height: 1.5em;
    }
  </style>
</head>

<body>
  <!-- we force the loading of the font awesome -->
  <i class="fas fa-camera fa-1x" style="color: rgba(0,0,0,0);"></i>
  <div id="graph-container"></div>
  <div class="control-bar" id="controls">
    <form id="ui">
      <span>Topology View</span>
      <label><input type="radio" name="topology" value="logical" checked="checked" />
        <i>Logical Topology</i></label>
      <label><input type="radio" name="topology" value="physical" />
        <i>Physical Topology</i></label>
      </label>
    </form>
  </div>

  <script>
    'use strict';

    Ogma.libraries['leaflet'] = L;

    var graph = {
      nodes: [
        { id: 'Router', data: { floorPlanY: 36, floorPlanX: 953 } },
        { id: 'Web Server', data: { floorPlanY: 72, floorPlanX: 903 } },
        { id: 'Switch', data: { floorPlanY: 476, floorPlanX: 953 } },
        { id: 'Admin Hub', data: { floorPlanY: 478, floorPlanX: 497 } },
        { id: 'Admin Workstation 1', data: { floorPlanY: 545, floorPlanX: 658 } },
        { id: 'Admin Workstation 2', data: { floorPlanY: 545, floorPlanX: 497 } },
        { id: 'Admin Workstation 3', data: { floorPlanY: 545, floorPlanX: 318 } },
        { id: 'Network Printer 1', data: { floorPlanY: 36, floorPlanX: 827 } },
        { id: 'Network Printer 2', data: { floorPlanY: 36, floorPlanX: 320 } },
        { id: 'Internet', data: { floorPlanY: 103, floorPlanX: 991 } },
        { id: 'Workstation 1', data: { floorPlanY: 334, floorPlanX: 335 } },
        { id: 'Workstation 2', data: { floorPlanY: 334, floorPlanX: 425 } },
        { id: 'Workstation 3', data: { floorPlanY: 294, floorPlanX: 392 } },
        { id: 'Workstation 4', data: { floorPlanY: 294, floorPlanX: 483 } },
        { id: 'Workstation 5', data: { floorPlanY: 334, floorPlanX: 554 } },
        { id: 'Workstation 6', data: { floorPlanY: 294, floorPlanX: 609 } },
        { id: 'Workstation 7', data: { floorPlanY: 334, floorPlanX: 645 } },
        { id: 'Workstation 8', data: { floorPlanY: 294, floorPlanX: 698 } },
        { id: 'Workstation 9', data: { floorPlanY: 334, floorPlanX: 762 } },
        { id: 'Workstation 10', data: { floorPlanY: 294, floorPlanX: 826 } },
        { id: 'Workstation 11', data: { floorPlanY: 334, floorPlanX: 859 } },
        { id: 'Workstation 12', data: { floorPlanY: 294, floorPlanX: 917 } },
        { id: 'Workstation 13', data: { floorPlanY: 151, floorPlanX: 552 } },
        { id: 'Workstation 14', data: { floorPlanY: 111, floorPlanX: 608 } },
        { id: 'Workstation 15', data: { floorPlanY: 151, floorPlanX: 642 } },
        { id: 'Workstation 16', data: { floorPlanY: 111, floorPlanX: 697 } },
        { id: 'Isle 1 Switch', data: { floorPlanY: 314, floorPlanX: 412 } },
        { id: 'Isle 2 Switch', data: { floorPlanY: 314, floorPlanX: 628 } },
        { id: 'Isle 3 Switch', data: { floorPlanY: 314, floorPlanX: 840 } },
        { id: 'Isle 4 Switch', data: { floorPlanY: 129, floorPlanX: 628 } },
        { id: 'Ethernet Switch', data: { floorPlanY: 194, floorPlanX: 953 } },
      ],
      edges: [
        { id: 'Admin to Hub 1', source: 'Admin Workstation 1', target: 'Admin Hub', attributes: { width: 1 } },
        { id: 'Admin to Hub 2', source: 'Admin Workstation 2', target: 'Admin Hub', attributes: { width: 1 } },
        { id: 'Admin to Hub 3', source: 'Admin Workstation 3', target: 'Admin Hub', attributes: { width: 1 } },
        { id: 'Server to Router', source: 'Web Server', target: 'Router', attributes: { width: 5 } },
        { id: 'Admin to Switch', source: 'Admin Hub', target: 'Switch', attributes: { width: 5 } },
        { id: 'Switch to Internet', source: 'Switch', target: 'Router', attributes: { width: 5 } },
        { id: 'Printer 1 Linking', source: 'Network Printer 1', target: 'Router', attributes: { width: 1 } },
        { id: 'Printer 2 Linking', source: 'Network Printer 2', target: 'Router', attributes: { width: 1 } },
        { id: 'W1 to Switch', source: 'Workstation 1', target: 'Isle 1 Switch', attributes: { width: 1 } },
        { id: 'W2 to Switch', source: 'Workstation 2', target: 'Isle 1 Switch', attributes: { width: 1 } },
        { id: 'W3 to Switch', source: 'Workstation 3', target: 'Isle 1 Switch', attributes: { width: 1 } },
        { id: 'W4 to Switch', source: 'Workstation 4', target: 'Isle 1 Switch', attributes: { width: 1 } },
        { id: 'W5 to Switch', source: 'Workstation 5', target: 'Isle 2 Switch', attributes: { width: 1 } },
        { id: 'W6 to Switch', source: 'Workstation 6', target: 'Isle 2 Switch', attributes: { width: 1 } },
        { id: 'W7 to Switch', source: 'Workstation 7', target: 'Isle 2 Switch', attributes: { width: 1 } },
        { id: 'W8 to Switch', source: 'Workstation 8', target: 'Isle 2 Switch', attributes: { width: 1 } },
        { id: 'W9 to Switch', source: 'Workstation 9', target: 'Isle 3 Switch', attributes: { width: 1 } },
        { id: 'W10 to Switch', source: 'Workstation 10', target: 'Isle 3 Switch', attributes: { width: 1 } },
        { id: 'W11 to Switch', source: 'Workstation 11', target: 'Isle 3 Switch', attributes: { width: 1 } },
        { id: 'W12 to Switch', source: 'Workstation 12', target: 'Isle 3 Switch', attributes: { width: 1 } },
        { id: 'W13 to Switch', source: 'Workstation 13', target: 'Isle 4 Switch', attributes: { width: 1 } },
        { id: 'W14 to Switch', source: 'Workstation 14', target: 'Isle 4 Switch', attributes: { width: 1 } },
        { id: 'W15 to Switch', source: 'Workstation 15', target: 'Isle 4 Switch', attributes: { width: 1 } },
        { id: 'W16 to Switch', source: 'Workstation 16', target: 'Isle 4 Switch', attributes: { width: 1 } },
        { id: 'Isle 1 to Switch', source: 'Isle 1 Switch', target: 'Ethernet Switch', attributes: { width: 3 } },
        { id: 'Isle 2 to Switch', source: 'Isle 2 Switch', target: 'Ethernet Switch', attributes: { width: 3 } },
        { id: 'Isle 3 to Switch', source: 'Isle 3 Switch', target: 'Ethernet Switch', attributes: { width: 3 } },
        { id: 'Isle 4 to Switch', source: 'Isle 4 Switch', target: 'Ethernet Switch', attributes: { width: 3 } },
        { id: 'Office To Internet', source: 'Ethernet Switch', target: 'Router', attributes: { width: 5 } },
        { id: 'To Internet', source: 'Router', target: 'Internet', attributes: { width: 10 } },
      ]
    };

    var ogma = new Ogma({
      graph: graph,
      container: 'graph-container'
    });

    var computerIcon = '\uf108';
    var internetIcon = '\uf0c2';
    var routerIcon = '\uf277';
    var switchIcon = '\uf362';
    var printerIcon = '\uf02f';
    var serverIcon = '\uf233';

    ogma.styles.addNodeRule({
      radius: 10,
      text: {
        content: function (node) {
          return node.getId();
        },
        backgroundColor: 'rgba(255, 255, 255, 0.2)',
        minVisibleSize: 0
      },
      color: 'white',
      outerStroke: {
        color: '#2171b5',
        width: 1
      },
      icon: {
        content: function (node) {
          var name = node.getId();
          if (/switch/i.test(name)) {
            return switchIcon;
          }
          if (/workstation/i.test(name)) {
            return computerIcon;
          }
          if (/printer/i.test(name)) {
            return printerIcon;
          }
          if (/router/i.test(name)) {
            return routerIcon;
          }
          if (/internet/i.test(name)) {
            return internetIcon;
          }
          return serverIcon;
        },
        font: 'Font Awesome 5 Free',
        color: '#2171b5',
        style: 'bold',
        minVisibleSize: 0
      }
    });

    ogma.styles.addEdgeRule({
      color: function (edge) {
        var width = edge.getAttribute('width');
        if (width === 1) {
          return '#bae4b3';
        }
        if (width < 5) {
          return '#a1dab4';
        }
        if (width < 10) {
          return '#41b6c4';
        }
        return '#225ea8';
      }
    })

    ogma.layouts.force({ locate: true });

    // these are the real dimensions of the image
    var floorPlanWidth = 3012;
    var floorPlanHeight = 1984;
    var floorPlanUrl = 'img/office-floorplan.png';

    // L.CRS.Simple world maps a world bound of 1000 units per side:
    // because the image is not squared we need to map the height
    // based on its ratio proportion
    var ratio = (floorPlanWidth / floorPlanHeight);
    var bounds = L.latLngBounds([[0, 0], [1000 / ratio, 1000]]);

    function toggleTopology() {

      return ogma.geo.toggle({
        // note that in L.CRS.Simple x and y are
        // longitude and latitude, respectively
        longitudePath: 'floorPlanX',
        latitudePath: 'floorPlanY',
        // set the custom layer as tiles object
        tiles: L.imageOverlay(floorPlanUrl, bounds),
        // Use a custom projection function
        crs: L.CRS.Simple,
        // Do not wrap coordinates: let the user to handle it
        wrapCoordinates: false,
        // when using custom projections zoom level can be negative too
        minZoomLevel: -2,
        // Transition time from Graph to Geo mode
        duration: 1000,
      }).then(function () {
        if (ogma.geo.enabled()) {
          var map = ogma.geo.getMap();
          map.fitBounds(bounds);
        }
      });
    }

    document.querySelector('#ui').addEventListener('change', function (evt) {
      toggleTopology();
    });

  </script>
</body>

</html>