Semi-Complex Shape

by Roman Bruckner

HTML

<html>

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

  </body>

</html>

JavaScript

var graph = new joint.dia.Graph();
var paper = new joint.dia.Paper({
  el: document.getElementById('paper'),
  width: 800,
  height: 600,
  model: graph,
  async: true
});

var Shape = joint.dia.Element.define('shape', {
  attrs: {
    body: {
      refWidth: '100%',
      refHeight: '100%',
      fill: 'gray',
      stroke: 'black'
    },
    statusLine: {
      x: 0,
      y: 0,
      width: 5,
      refHeight: '100%',
      fill: 'yellow'
    },
    headerLabel: {
      x: 30,
      y: 10,
      fill: 'white',
      textAnchor: 'start',
      textVerticalAnchor: 'top',
      fontWeight: 'bold',
      fontFamily: 'sans-serif',
      fontSize: 15,
      text: '1234 User'
    },
    headerIcon: {
      xlinkHref: 'https://via.placeholder.com/15',
      height: 15,
      width: 15,
      x: 10,
      y: 10
    },
    descriptionIcon: {
      xlinkHref: 'https://via.placeholder.com/20',
      refHeight: -60,
      width: 20,
      x: 10,
      y: 40
    },
    descriptionLabel: {
      x: 40,
      refY: '50%',
      refY2: 10,
      fill: 'lightgray',
      textAnchor: 'start',
      textVerticalAnchor: 'middle',
      fontWeight: 'bold',
      fontFamily: 'sans-serif',
      fontSize: 14,
      text: 'Here\'s some description about this element. It\'s automatically wrap the text',
      textWrap: {
        width: -50,
        height: -40,
        ellipsis: true
      }
    }
  }
}, {
  markup: [{
    tagName: 'rect',
    selector: 'body'
  }, {
    tagName: 'rect',
    selector: 'statusLine'
  }, {
    tagName: 'text',
    selector: 'headerLabel'
  }, {
    tagName: 'image',
    selector: 'headerIcon'
  }, {
    tagName: 'image',
    selector: 'descriptionIcon'
  }, {
    tagName: 'text',
    selector: 'descriptionLabel'
  }]
}, {

});

var shape1 = new Shape();
shape1.resize(200, 100);
shape1.position(100, 100);
shape1.addTo(graph);

var shape2 = new Shape({
  attrs: {
    statusLine: {
      fill: 'red'
    }
  }
});
shape2.resize(200,...