JointJS - Custom Element View
An example how to create a JointJS element view with custom rendering/updating.
by Roman Bruckner
HTML
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/1.0.3/joint.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/1.0.3/joint.min.css">
<!-- JointJS Fiddle -->
<div id="paper"></div>
CSS
#paper {
display: inline-block;
border: 1px solid gray;
}
JavaScript
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: $('#paper'),
width: 600,
height: 600,
gridSize: 20,
model: graph
});
joint.shapes.custom = {};
joint.shapes.custom.Element = joint.dia.Element.extend({
defaults: _.defaultsDeep({
type: 'custom.Element',
fillColor: 'red',
outlineColor: 'black',
activeTab: 0,
numberOfTabs: 1,
faded: false
})
});
joint.shapes.custom.ElementView = joint.dia.ElementView.extend({
events: {
'dblclick': 'onDblClick',
'click .tab': 'onTabClick'
},
init: function() {
var model = this.model;
this.listenTo(model, [
'change:activeTab',
'change:fillColor',
'change:outlineColor',
].join(' '), this.update);
this.listenTo(model, 'change:faded', this.toggleFade);
this.listenTo(model, 'change:numberOfTabs', this.render);
},
render: function() {
var rootVEl = this.vel;
rootVEl.empty();
var edges = this.model.get('edges');
edges.forEach(function(edge) {
var path = V('path').attr('d', `M ${edge.start.x} ${edge.start.y} ${edge.end.x} ${edge.end.y}`);
path.appendTo(rootVEl);
});
},
update: function() {
this.updateBody();
this.updateText();
this.updateTabs();
this.toggleFade();
},
updateBody: function() {
var model = this.model;
var bodyAttributes = {
width: model.prop('size/width'),
height: model.prop('size/height'),
fill: model.prop('fillColor'),
stroke: model.prop('outlineColor')
};
this.vBody.attr(bodyAttributes);
},
updateTabs: function() {
var model = this.model;
var numberOfTabs = model.prop('numberOfTabs');
var length = model.prop('size/width') / numberOfTabs;
var activeTab = model.prop('activeTab');
var vTabs = this.vTabs;
for (var i = 0; i < numberOfTabs; i++) {
var isActive = (activeTab === i);
var offset = +isActive;
vTabs[i].attr({
width: length - 2 *...