Performance

Tips for performance improvements for usual JointJS applications.

by Roman Bruckner

HTML

<html>

  <head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.5.5/joint.css" />
  </head>

  <body>
    <!-- content -->


    <div id="canvas"></div>
    <div id="perf"></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.20/lodash.min.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.5.5/joint.js"></script>

  </body>

</html>

JavaScript

// JointJS Performance tips

// Overall goals
// -------------
// 1. reduce number of DOM elements (See async.html demo)
// 2. avoid asking the browser for element bounding boxes as much as possible

// Number of elements 0 - ?
var COUNT = 5000;
var RELATIONS = 1;
// Async rendering true/false
// true: does not block the UI
var ASYNC = true;

var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
  el: document.getElementById('canvas'),
  width: COUNT / 2 * 110,
  height: 500,
  model: graph,
  async: ASYNC,
  frozen: true,
  // Avoid using joint.dia.Paper.sorting.EXACT
  // It's extremely slow for large amounts of elements.
  // There is no big difference between sorting APPROX and NONE in terms of performance.
  sorting: joint.dia.Paper.sorting.APPROX,
  // To avoid measuring of the SVGElement magnet size, you can calculate
  // the anchor point for the links manually.
  defaultConnectionPoint: {
    name: 'anchor'
  },
  defaultAnchor: (view, _0, _1, _2, endType) => {
    const bbox = view.model.getBBox();
    return endType === 'source' ? bbox.bottomMiddle() : bbox.topMiddle();
  },
});

var Shape = joint.dia.Element.define('Shape', {
  size: {
    width: 100,
    height: 50
  },
  attrs: {
    body: {
      // If the `ref` attribute is not defined all the metrics for calc() expressions
      // (width, height, x, y) are taken from the model.
      // All calculation are done just in Javascript === very fast.
      // Avoid using `ref: selector` attribute if you don't need the browser
      // to measure the size of the element defined by the selector.
      width: 'calc(w)',
      height: 'calc(h)',
      stroke: 'red',
      strokeWidth: 2,
      fill: 'lightgray',
      rx: 5,
      ry: 5
    },
    label: {
      fill: 'black',
      fontSize: 14,
      fontFamily: 'sans-serif',
      // Please see the `ref-width` & `ref-height` comment.
      x: 'calc(0.5 * w)',
      y: 'calc(0.5 * h)',
      // Do not use special attribute `x-alignment`...