JointJS - Spinner Element

by Roman Bruckner

HTML

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

CSS

.joint-paper {
  display: inline-block;
  border: 1px solid gray;
}

JavaScript

class Spinner extends joint.dia.Element {

    defaults() {
        return {
            ...super.defaults,
            type: 'Spinner',
            size: {
                width: 60,
                height: 80
            },
            spin: true,
            attrs: {
                body: {
                    width: 'calc(w)',
                    height: 'calc(h)',
                },
                fan: {
                    d: V.createSlicePathData(0, 20, 0, 5)
                },
                fanGroup: {
                    transform: 'translate(calc(w/2),calc(h/2))'
                },
                label: {
                    text: 'Spinner',
                    textVerticalAnchor: 'top',
                    x: 'calc(0.5*w)',
                    y: 'calc(h+10)'
                },
            }
        };
    }

    preinitialize() {
        this.markup = joint.util.svg/* xml */`
            <rect @selector="body"
                stroke="#333"
                stroke-width="2"
                fill="#fff"
                rx="5"
                ry="5"
            />
            <g @selector="fanGroup">
                <path @selector="fan"
                    stroke="red"
                    stroke-width="2"
                    fill="white"
                />
            </g>
            <text @selector="label"
                font-size="14"
                font-family="sans-serif"
                fill="#333"
                text-anchor="middle"
            />
        `;
    }
}
const SpinnerView = joint.dia.ElementView.extend({

    presentationAttributes: joint.dia.ElementView.addPresentationAttributes({
        spin: ['SPIN'],
    }),

    initFlag: [joint.dia.ElementView.Flags.RENDER, 'SPIN'],

    spinAnimation: null,

    confirmUpdate(...args) {
        let flags = joint.dia.ElementView.prototype.confirmUpdate.call(this, ...args);
        if (this.hasFlag(flags, 'SPIN')) {
            this.toggleSpin();
            flags = this.removeFlag(flags,...