JointJS - Shape with image and labels

prevent contextmenu. https://github.com/clientIO/joint/issues/2658

by Roman Bruckner

HTML

<script src="https://cdn.jsdelivr.net/npm/@joint/[email protected]/dist/joint.min.js"></script>
<div id="paper"></div>

JavaScript

const { dia, shapes, util, mvc } = joint;

class MyElement extends dia.Element {
  defaults() {
    return {
      ...super.defaults,
      type: 'MyElement',
      size: {
        width: 100,
        height: 80,
      },
      attrs: {
        body: {
          width: 'calc(w)',
          height: 'calc(h)',
          fill: '#aaa',
          stroke: '#333333',
          strokeWidth: 2,
          rx: 6,
          ry: 6,
        },
        icon: {
          width: 'calc(w)',
          height: 'calc(h/2)',
          y: 'calc(h/4)',
          x: 0,
          xlinkHref: 'https://picsum.photos/200/200',
        },
        labels: {
          fontSize: 14,
          fontFamily: 'sans-serif',
          fill: '#333333',
          textAnchor: 'middle',
          x: 'calc(w/2)',
        },
        label1: {
          text: 'Label 1',
          y: 5,
          textVerticalAnchor: 'top',
        },
        label2: {
          text: 'Label 2',
          textVerticalAnchor: 'bottom',
          y: 'calc(h-5)',
        },
      },
    };
  }

  preinitialize() {
    this.markup = [
      {
        tagName: 'rect',
        selector: 'body',
      },
      {
        tagName: 'image',
        selector: 'icon',
      },
      {
        tagName: 'text',
        selector: 'label1',
        groupSelector: 'labels',
      },
      {
        tagName: 'text',
        selector: 'label2',
        groupSelector: 'labels',
      },
    ];
  }
}

const cellNamespace = {
  ...shapes,
  MyElement,
};

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

const paper = new dia.Paper({
  model: graph,
  background: {
    color: '#F8F9FA',
  },
  async: true,
  cellViewNamespace: cellNamespace,
});

document.getElementById('paper').appendChild(paper.el);

const el1 = new MyElement({
  position: { x: 100, y: 50 },
  size: { width: 200, height: 200 },
  attrs: {
    label1: {
      text: 'My Element 1',
   ...