JointJS - Attributes Binding
by Roman Bruckner
HTML
<html>
<body>
<div id="paper"></div>
<script src="https://cdn.jsdelivr.net/npm/@joint/[email protected]/dist/joint.min.js"></script>
</body>
</html>
CSS
.joint-paper {
display: inline-block;
border: 1px solid gray;
}
JavaScript
class MyShape extends joint.dia.Element {
defaults() {
return {
...super.defaults,
type: 'MyShape',
color: 'gray',
name: 'My Shape',
number: 0,
size: {
width: 100,
height: 80,
},
attrs: {
body: {
width: 'calc(w)',
height: 'calc(h)',
stroke: '#333333',
strokeWidth: 2,
},
label: {
text: 'Image',
textVerticalAnchor: 'middle',
textAnchor: 'middle',
x: 'calc(0.5*w)',
y: 'calc(0.5*h)',
fontSize: 14,
fontFamily: 'sans-serif',
fill: '#ffffff',
},
},
};
}
preinitialize() {
this.markup = [
{
tagName: 'rect',
selector: 'body',
},
{
tagName: 'text',
selector: 'label',
},
];
}
initialize(...args) {
super.initialize(...args);
this.on('change', ({ changed }, opt) => {
if ('color' in changed || 'name' in changed || 'number' in changed) {
this.updateBindings(opt);
}
});
this.updateBindings();
}
updateBindings(opt) {
this.attr(
{
body: {
fill: this.get('color'),
},
label: {
text: `${this.get('name')} ${this.get('number')}`,
},
},
opt,
);
}
toJSON() {
const json = super.toJSON();
// presentation attributes are controlled via
// top level attributes only (color, name, number)
delete json.attrs;
// element is never rotated
delete json.angle;
// size will never change
delete json.size;
return json;
}
}
const shapes = { MyShape };
const graph = new joint.dia.Graph(
{},
{ ...joint.shapes, cellNamespace: shapes },
);
const paper = new joint.dia.Paper({
el: document.getElementById('paper'),
width: 800,
height: 800,
model:...