JointJS + SVGPanZoom

by Roman Bruckner

HTML

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<html>

    <!-- content -->
    <div id="paper" style="border: 1px solid black;"></div>

    <!-- dependencies -->

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

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/svg-pan-zoom.min.js"></script>

JavaScript

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

const shapeA = new joint.shapes.standard.Rectangle({
    attrs: { label: { text: 'Rect' }}
});
const shapeB = new joint.shapes.standard.Ellipse({
    attrs: { label: { text: 'Ellipse' }}
});
shapeA.position(50,100);
shapeB.position(200,100);
shapeA.resize(50, 50);
shapeB.resize(50, 50);
shapeA.addTo(graph);
shapeB.addTo(graph);

const panZoom = svgPanZoom(paper.svg, {
      viewportSelector: paper.layers,
      zoomEnabled: true,
      panEnabled: false,
      controlIconsEnabled: true,
      maxZoom: 2,
      minZoom: 0.1,
      onUpdatedCTM: (function() {
          let currentMatrix = paper.matrix();
          return function onUpdatedCTM(matrix){
              const { a, d, e, f } = matrix;
              const { a: ca, d: cd, e: ce, f: cf } = currentMatrix;
              const translateChanged = (e !== ce || f !== cf)
              if (translateChanged)
                  paper.trigger('translate', e - ce, f - cf, {});
              const scaleChanged = (a !== ca || d !== cd);
              if (scaleChanged)
                  paper.trigger('scale', a, d, {});
	      if (scaleChanged || translateChanged) {
                 paper.trigger('transform', matrix, {});
              }
              currentMatrix = matrix;
          }
      })()
  });
  
paper.on('blank:pointerdown', function() {
  panZoom.enablePan();
});
  
paper.on('blank:pointerup', function() {
  panZoom.disablePan();
});