What I am trying to do is make a element with custom class for ports and path so that I can add an element with custom path and my own markup for ports.This way when I create an element I will pass dynamic path for its shape just like elements of path class behave and as I have also extended from PortsModelInterface I will also have my own markup for ports. This whole effort is to make svg scalable for zomming. Previously I was using html custom element with my custom ports which was working fine but html of custom elements wasn't scaling on zooming
var graph = new joint.dia.
var paper = new joint.dia.Paper({
el: $('#paper'),
width: 800,
height: 600,
gridSize: 1,
model: graph,
snapLinks: true,
embeddingMode: true
});
joint.shapes.custom1={};
joint.shapes.custom1.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '<g class="rotatable"><g class="scalable"><rect class = "myrect"/></g><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port<%= id %>"><circle class="port-body"/></g>',
defaults: joint.util.deepSupplement({
type: 'html.Element',
size: { width: 200, height: 110 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: true},
rect: {
stroke: 'none', 'fill-opacity': 0, width: 300, height: 210,
},
circle: {
r: 6, //circle radius
magnet: true,
left:0,
stroke: 'gray'
},
'.inPorts circle': { fill: 'gray', magnet: 'passive', type: 'input', y: 0},
'.outPorts circle': { fill: 'gray', type: 'output' }
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function (portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portCircleSelector = portSelector + '>circle';
attrs[portCircleSelector] = { port: { id: portName || _.uniqueId(type), type: type } };
attrs[portSelector] = { ref: 'rect', 'ref-x': (index + 1) * (0.55 / total)};
if (selector === '.outPorts') {
attrs[portSelector]['ref-dy'] = 15;
}
return attrs;
}
}));
joint.shapes.custom1.Atomic = joint.shapes.custom1.Element.extend({
markup: '<g class="rotatable"><g class="scalable"><path/></g><text/></g>',
defaults: joint.util.deepSupplement({
type: 'basic.Path',
size: { width: 60, height: 60 },
attrs: {
'path': { fill: '#FFFFFF', stroke: 'black' },
'text': { 'font-size': 14, text: '', 'text-anchor': 'middle', 'ref-x': .5, 'ref-dy': 20, ref: 'path', 'y-alignment': 'middle', fill: 'black', 'font-family': 'Arial, helvetica, sans-serif' }
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
var a2 = new joint.shapes.custom1.Atomic({
position: { x: 50, y: 260 },
size: { width: 100, height: 100 },
attrs: {
path: { d: 'M 30 0 L 60 30 30 60 0 30 z' },
text: {
text: 'Diamond',
'ref-y': .5 // basic.Path text is originally positioned under the element
}
},
inPorts: ['in'],
outPorts: ['out']
});
graph.addCells([a2])
The element is added in graph but some how the ports don't show up. I don't have proper concept of adding classes so please any help will be greatly appreciated. Thanks. Fiddle example
What I am trying to do is make a element with custom class for ports and path so that I can add an element with custom path and my own markup for ports.This way when I create an element I will pass dynamic path for its shape just like elements of path class behave and as I have also extended from PortsModelInterface I will also have my own markup for ports. This whole effort is to make svg scalable for zomming. Previously I was using html custom element with my custom ports which was working fine but html of custom elements wasn't scaling on zooming
var graph = new joint.dia.
var paper = new joint.dia.Paper({
el: $('#paper'),
width: 800,
height: 600,
gridSize: 1,
model: graph,
snapLinks: true,
embeddingMode: true
});
joint.shapes.custom1={};
joint.shapes.custom1.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '<g class="rotatable"><g class="scalable"><rect class = "myrect"/></g><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port<%= id %>"><circle class="port-body"/></g>',
defaults: joint.util.deepSupplement({
type: 'html.Element',
size: { width: 200, height: 110 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: true},
rect: {
stroke: 'none', 'fill-opacity': 0, width: 300, height: 210,
},
circle: {
r: 6, //circle radius
magnet: true,
left:0,
stroke: 'gray'
},
'.inPorts circle': { fill: 'gray', magnet: 'passive', type: 'input', y: 0},
'.outPorts circle': { fill: 'gray', type: 'output' }
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function (portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portCircleSelector = portSelector + '>circle';
attrs[portCircleSelector] = { port: { id: portName || _.uniqueId(type), type: type } };
attrs[portSelector] = { ref: 'rect', 'ref-x': (index + 1) * (0.55 / total)};
if (selector === '.outPorts') {
attrs[portSelector]['ref-dy'] = 15;
}
return attrs;
}
}));
joint.shapes.custom1.Atomic = joint.shapes.custom1.Element.extend({
markup: '<g class="rotatable"><g class="scalable"><path/></g><text/></g>',
defaults: joint.util.deepSupplement({
type: 'basic.Path',
size: { width: 60, height: 60 },
attrs: {
'path': { fill: '#FFFFFF', stroke: 'black' },
'text': { 'font-size': 14, text: '', 'text-anchor': 'middle', 'ref-x': .5, 'ref-dy': 20, ref: 'path', 'y-alignment': 'middle', fill: 'black', 'font-family': 'Arial, helvetica, sans-serif' }
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
var a2 = new joint.shapes.custom1.Atomic({
position: { x: 50, y: 260 },
size: { width: 100, height: 100 },
attrs: {
path: { d: 'M 30 0 L 60 30 30 60 0 30 z' },
text: {
text: 'Diamond',
'ref-y': .5 // basic.Path text is originally positioned under the element
}
},
inPorts: ['in'],
outPorts: ['out']
});
graph.addCells([a2])
The element is added in graph but some how the ports don't show up. I don't have proper concept of adding classes so please any help will be greatly appreciated. Thanks. Fiddle example
Share Improve this question edited Jul 16, 2015 at 10:57 Achilles asked Jul 12, 2015 at 13:15 AchillesAchilles 5197 silver badges27 bronze badges 9-
What does this have to do with
backbone.js
? – ivarni Commented Jul 12, 2015 at 13:29 - 2 Joint.js is built over backbone.js, this whole mechanism of extending classes is derived from backbone. Should'nt I add this tag?? – Achilles Commented Jul 12, 2015 at 13:38
- 1 Is there anyway you could make a fiddle or something so we can run the code and see it fail, and then try things to see if we can make it work? I'm not sure you're going to find someone with joint.js, but if you give us a chance to play, we may figure it out. – Guy Schalnat Commented Jul 16, 2015 at 2:58
- 1 Just made a fiddle of it. link is in post. – Achilles Commented Jul 16, 2015 at 10:58
- Here's a JSFiddle of a working demo of a custom element with custom ports. – c.hill Commented Jul 24, 2015 at 10:48
1 Answer
Reset to default 6I suggest to define an element with custom markup for the shape and ports. Both markups should contain an SVG path, so you can set an arbitrary path data d
via model.attr()
on them.
joint.shapes.devs.GenericModel = joint.shapes.devs.Model.extend({
markup: '<g class="rotatable"><g class="scalable"><path class="body"/></g><text class="label"/><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port port<%= id %>"><path class="port-body"/><text class="port-label"/></g>',
defaults: joint.util.deepSupplement({
type: 'devs.GenericModel'
}, joint.shapes.devs.Model.prototype.defaults)
});
Tell the paper to use devs.ModelView
for rendering.
joint.shapes.devs.GenericModelView = joint.shapes.devs.ModelView;
Now you can set or change d
attribute for the shape and ports anytime you wish.
var model = new joint.shapes.devs.GenericModel({
attrs: {
'.body': { d: 'M 0 0 0 50 50 50 z'},
'.port-body': { d: 'M 0 0 10 0 10 10 0 10 z'}
}
});
model.attr('.body/d', 'M 25 0 50 50 0 50 z');
JS Fiddle: http://jsfiddle/kumilingus/kge023bc/