Isometric View

by Roman Bruckner

HTML

<html>

  <head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.2.0/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.15/lodash.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.2.0/joint.js"></script>

  </body>

</html>

JavaScript

var gridSize = 20;
var gridCount = 20;

var graph = new joint.dia.Graph();
var paper = new joint.dia.Paper({
  el: document.getElementById('paper'),
  width: 1000,
  height: 1000,
  restrictTranslate: {
    x: 0,
    y: 0,
    width: gridSize * gridCount,
    height: gridSize * gridCount
  },
  model: graph,
  gridSize,
  async: true,
  sorting: joint.dia.Paper.sorting.APPROX,
  defaultConnectionPoint: {
    name: 'boundary'
  },
  defaultRouter: {
    name: 'orthogonal'
  }
});

let data = [];
let j = gridCount;
for (var i = 0; i <= j; i++) {
  data.push(`M 0,${i * gridSize} ${j * gridSize},${i * gridSize}`);
  data.push(`M ${i * gridSize},0 ${i * gridSize},${j * gridSize}`);
}

const grid = V('path').attr({
  'd': data.join(' '),
  'fill': 'none',
  'stroke': 'lightgray'
}).node;

paper.layers.prepend(grid);

const Box = joint.dia.Element.define('isometric.Box', {
  size: {
    width: 100,
    height: 40
  },
  attrs: {
    root: {
      magnetSelector: 'base'
    },
    base: {
      refWidth: '100%',
      refHeight: '100%',
      stroke: 'gray',
      fill: 'lightgray',
      strokeWidth: 2
    },
    body: {
      d: 'M 0 0 -20 -20 M 80 -20 100 0 M 80 20 100 40 M -20 20 0 40',
      stroke: 'red',
      strokeWidth: 2,
      fill: 'none'
    },
    image: {
      xlinkHref: 'https://uploads-ssl.webflow.com/5773a44a2de39fb074c75653/57ce8fc2b6529fe831fcb423_Rappid%20Logo%20White%20160.png',
      width: 60,
      height: 40,
      x: 20 - 20,
      y: 0 - 20
    },
    top: {
      x: -20,
      y: -20,
      refWidth: '100%',
      refHeight: '100%',
      stroke: 'red',
      strokeWidth: 2,
      fill: 'red',
      fillOpacity: 0.3
    },
    label: {
      refX: '50%',
      refDy: 10,
      textVerticalAnchor: 'top',
      textAnchor: 'middle',
      fontFamily: 'sans-serif',
      fontSize: 18
    }
  }
}, {
  markup: [{
    tagName: 'rect',
    selector: 'base'
  }, {
    tagName: 'path',
    selector: 'body'
  }, {
    tagName: 'rect',
    selector:...