I have an element defined as this:
var m1 = new joint.shapes.devs.Model({
position: { x: 100, y: 50 },
size: { width: 190, height: 50 },
inPorts: ['in'],
outPorts: ['out'],
attrs: {
'.label': { text: 'Model','ref-x': .4, 'ref-y': .25 ,fill: '#fefefe',
'font-size': 14,
'font-weight': 'bold',
'font-variant': 'small-caps' },
rect: { fill: '#fefefe'},
'.inPorts circle': { r:5 ,fill: '#16A085' ,magnet: 'passive', type: 'input'},
'.outPorts circle': { r:5, fill: '#E74C3C',magnet: 'passive',type: 'output' },
}
THe question is how can I get the '.label' attribute?
E.g, I need to get the text "Model", what should I do?
If I want to get the 'fill' attr of 'rect' , I can simply use m1.get('attrs').rect.fill.
But I don't know HOW TO GET the '.label' attr.
Use the attr() method for both setting attributes and getting them back:
m1.attr('.label/text') // 'Model'
m1.attr('.label/text', 'New Model')
m1.attr('.label/text') // 'New Model'
'/' is a path separator into the nested attrs object.
var rootnode = new joint.shapes.basic.Circle({
position: { x: 20, y: 220 },
size: { width: 60, height: 30 },
attrs: {
text: { text: 'parent' },
circle: { fill: 'yellow', hasChildren:false }
},
name: 'parent'
});
graph.addCell(rootnode);
Related
I am creating a rectangle and writing a text inside it, but the text comes out of the rectangle:
Is there any way to keep the text within the rectangle in jointJs?
Here is my code:
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({ el: $('#paper'), width: 650, height: 250, gridSize: 1, model: graph });
var r1 = new joint.shapes.basic.Rect({
position: { x: 20, y: 20 },
size: { width: 200, height: 200 },
attrs: { rect: { fill: '#E74C3C' }, text: { text: 'this text is coming out from rectangle' ,
fontSize: 14,
fill: '#2b7aff'} }
});
graph.addCells([r1]);
Actually i found the answer of my question from jointJs documentation
https://resources.jointjs.com/docs/jointjs/v2.0/joint.html#util.breakText
but there is a problem they(jointjs) described only two parameters
as
joint.util.breakText('this is quite a long text', { width: 50 })
// 'this is\nquite a\nlong\ntext'
but actually there is a third parameter "styles" that is also required
so actual solution is
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({ el: $('#paper'), width: 650, height: 250, gridSize: 1, model: graph });
var text = joint.util.breakText('This is very very very very very very very very very very very very very very very very very very very very very very long text', { width: 20, height:20}, {lineHeight: 1.2});
var r1 = new joint.shapes.basic.Rect({
position: { x: 70, y: 30 },
size: { width: 100, height: 80 },
attrs: { rect: { fill: '#F1C40F' }, text: { text: text } }
});
r1.embed(r1);
graph.addCells([r1]);
Can anybody please guide me on how to apply textpath attribute to a link label text in Joint JS?
I have created smooth links that follows a particular path, I want my label text to appear along that path.
Code Snippet:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="joint.css" />
<script src="jquery.js"></script>
<script src="lodash.js"></script>
<script src="backbone.js"></script>
<script src="joint.js"></script>
</head>
<body>
<div id="myholder"></div>
<script type="text/javascript">
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el : $('#myholder'),
width : 600,
height : 200,
model : graph,
gridSize : 1
});
var rect = new joint.shapes.basic.Rect({
position : {
x : 100,
y : 30
},
size : {
width : 100,
height : 30
},
attrs : {
rect : {
fill : 'blue'
},
text : {
text : 'my box',
fill : 'white'
}
}
});
var rect2 = rect.clone();
rect2.translate(300);
var link = new joint.dia.Link({
source : {
id : rect.id
},
target : {
id : rect2.id
},
attrs : {
'.connection' : {
'stroke' : 'lightgray',
'stroke-width' : 3,
'stroke-dasharray' : '5 2'
},
'.marker-source' : {
d : 'M 10 0 L 0 5 L 10 10 z',
fill : 'white'
}
},
smooth : true,
labels : [ {
position : .5,
attrs : {
text : {
text : 'LinkLabel',
fill : 'lightgray'
}
}
} ]
});
graph.addCells([ rect, rect2, link ]);
</script>
</body>
</html>
I am not sure if there is a textpath attribute for a link exposed for jointjs. However the demo does use the label attribute with positions
labels: [
{ position: 25, attrs: { text: { text: '1..n' } }},
{ position: 0.45, attrs: { text: { text: 'multiple', fill: 'white', 'font-family': 'sans-serif' }, rect: { stroke: '#31d0c6', 'stroke-width': 20, rx: 5, ry: 5 } }},
{ position: 0.55, attrs: { text: { text: 'labels', fill: 'white', 'font-family': 'sans-serif' }, rect: { stroke: '#31d0c6', 'stroke-width': 20, rx: 5, ry: 5 } }},
{ position: -25, attrs: { text: { text: '*' } }}
]
this is for the last link in the demo
http://resources.jointjs.com/demos/links
A bit late but maybe someone will find it useful:
You can use the textPath attribute as used in the demo linked by the other answer:
It uses the smooth connector.
var link8 = new joint.shapes.standard.ShadowLink({
source: { x: 10, y: 280 },
target: { x: 440, y: 280 },
vertices: [{ x: 150, y: 350 }, { x: 300, y: 280 }],
smooth: true,
markup: [{
tagName: 'path',
selector: 'shadow',
attributes: {
'fill': 'none'
}
}, {
tagName: 'path',
selector: 'line',
attributes: {
'fill': 'none'
}
}, {
tagName: 'text',
selector: 'label'
}],
attrs: {
line: {
stroke: '#3c4260'
},
label: {
textPath: {
selector: 'line',
startOffset: '50%'
},
textAnchor: 'middle',
textVerticalAnchor: 'middle',
text: 'Label Along Path',
fill: '#f6f6f6',
fontSize: 15,
fontWeight: 'bold',
fontFamily: 'fantasy'
}
}
});
When cloning Objects I know how to change attributes for example>
Clone Object 1 2 times var m5 = m1.clone().translate(300, 0).attr('rect/fill', '#F69F43').attr('.label/text', 'Model 2').addTo(graph);
here changing name to attr label/text
but having this element:
var m1 = new joint.shapes.devs.Model({
position: { x: 300, y: 50 },
size: { width: 120, height: 150 },
inPorts: ['in1','in2','in3','in4'],
outPorts: ['out'],
attrs: { '.label': { text: 'Model1', 'ref-x': .4, 'ref-y': .2 }, rect: { fill: '#2ECC71' },
'.inPorts circle': { fill: '#16A085', magnet: 'passive', type: 'input' },
'.outPorts circle': { fill: '#E74C3C', type: 'output' },
'.name': { name: 'Bloque1' } } }).addTo(graph);
How to clone changing .inPorts Circle fill ???
Thanks
var m5 = m1.clone().attr('.inPorts circle/fill', 'red').addTo(graph); changes color of each input ports to red. You can change color of particular port with m5.attr('.inPorts>.port3>circle/fill' ,'green')
I'm a newbie in jointjs. Today I have a small example as below:
I have a start Activity
var startEndActivity = function (x, y, name, fillColor, textColor, size) {
fillColor = fillColor || '#007FBE';
textColor = textColor || "#000";
size = size || { width: 100, height: 40 };
var rect = new joint.shapes.basic.Rect({
position: { x: x, y: y },
size: size,
attrs: {
rect: { fill: fillColor, rx: 5, ry: 5, 'stroke-width': 1, stroke: '#002F5D' },
text: {
text: name, fill: textColor,
'font-size': 14, 'font-family': 'sans-serif'
}
}
});
graph.addCell(rect);
return rect;}
I have a condition Activity
var activityDecision = function (x, y, name, fillColor, textColor, size{
fillColor = fillColor || '#BF664C';
textColor = textColor || "#080808";
size = size || { width: 200, height: 60 };
var node = new joint.shapes.basic.Rhombus({
position: { x: x, y: y },
size: size,
});
node.attr({
rect: { fill: fillColor, 'stroke-width': 1, stroke: 'white' },
text: {
text: name, fill: textColor,
}
});
graph.addCell(node);
return node;}
I want to click on start activity and I can draw a arrow to connect between 2 elements. Thank you so much
The most common approach that I know of is to use ports on your elements. This link should get you started on that route:
WORKING WITH PORTS
If you prefer to have the entire element behave as a port you need to look into the "magnetic" attribute. This link should help you get started researching what you need (especially the first answer):
How to interactively create links in JointJS
I found solution for this. Thank you so much. Just add more attribute like this
el.attr('rect/magnet', true).attr('text/pointer-events', 'none');
function create(type) {
var link = new joint.dia.Link({
source: { x: 10, y: 20 },
target: { x: 350, y: 20 },
attrs: {}
});
link.prop({...});
link.addTo(graph)
}
//init connection:
new joint.dia.Link({
source: { id: 'source-id' },
target: { id: 'target-id', port: 'port_id'}
});
In order to connect two element you have to work with Ports (documentation):
My best advice for you is to learn how to implement ports by looking in the JointJS source code, as a reference look for object: joint.shapes.devs.Model (live demo + source code inside)
something like this:
var myRect = joint.shapes.devs.Model.extend({
portMarkup: '<circle class="port-body myCustomClass"/>',
defaults: _.defaultsDeep({
type: 'myRect',
}, joint.shapes.basic.Generic.prototype.defaults),
});
and inside of startEndActivity function change the var rect to:
var startRect = new myRect({
position: { x: x, y: y },
size: size,
attrs: {
rect: { fill: fillColor, rx: 5, ry: 5, 'stroke-width': 1, stroke: '#002F5D' },
text: {
text: name, fill: textColor,
'font-size': 14, 'font-family': 'sans-serif'
}
},
ports: {
groups: {
'out': {
position: {
name: 'right'
},
attrs: {
'.port-label': {
fill: '#000'
},
'.port-body': {
fill: '#fff',
stroke: '#000',
r: 10,
magnet: true
}
},
label: {
position: {
name: 'right',
args: {
y: 10
}
}
}
}
}
});
do the same for the second element.
I'm trying to use JointJS with ports feature:
(...)
var model = joint.shapes.devs.Model({
size: { width: width, height: height },
label: node.label,
inPorts: node.inputPorts,
outPorts: node.outputPorts,
attrs: {
'.label': { text: node.label, 'ref-x': .4, 'ref-y': .2 },
rect: { fill: '#2ECC71' },
'.inPorts circle': { fill: '#16A085' },
'.outPorts circle': { fill: '#E74C3C' }
}
(...)
But input ports appears on the left and output ports on the right.
I want input ports on the top and output on the bottom.
Which is the best way to change the port position to Top-Bottom using joint.shapes.devs.Model ?
Thanks in advance.
The positions of ports are calculated in devs.Model.prototype.getPortAttrs. What you can do is just swap x and y port coordinates like in the example below.
joint.shapes.devs.Model = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '<g class="rotatable"><g class="scalable"><rect class="body"/></g><text class="label"/><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port port<%= id %>"><circle class="port-body"/><text class="port-label"/></g>',
defaults: joint.util.deepSupplement({
type: 'devs.Model',
size: { width: 1, height: 1 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: false },
'.body': {
width: 150, height: 250,
stroke: 'black'
},
'.port-body': {
r: 10,
magnet: true,
stroke: 'black'
},
text: {
fill: 'black',
'pointer-events': 'none'
},
'.label': { text: 'Model', 'ref-x': 10, 'ref-y': .2, 'ref': '.body' },
// CHANGED: find better positions for port labels
'.inPorts .port-label': { dy:-30, x: 4 },
'.outPorts .port-label':{ dy: 15, x: 4 }
//
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function(portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portLabelSelector = portSelector + '>.port-label';
var portBodySelector = portSelector + '>.port-body';
attrs[portLabelSelector] = { text: portName };
attrs[portBodySelector] = { port: { id: portName || _.uniqueId(type) , type: type } };
// CHANGED: swap x and y ports coordinates ('ref-y' => 'ref-x')
attrs[portSelector] = { ref: '.body', 'ref-x': (index + 0.5) * (1 / total) };
// ('ref-dx' => 'ref-dy')
if (selector === '.outPorts') { attrs[portSelector]['ref-dy'] = 0; }
//
return attrs;
}
}));
JS Fiddle: http://jsfiddle.net/kumilingus/L2f73cbf/
Update:
Here is an example how to achieve the same with JointJS v1.0.1+.
There is no need for extending the class with PortsModelInterface anymore. The ports API is now implemented by joint.dia.Element i.e. arbitrary element can be enriched with ports easily.
var shape = new joint.shapes.devs.Model({
inPorts: ['in1', 'in2'],
outPorts: ['out1', 'out2'],
ports: {
groups: {
'in': { position: 'top'},
'out': { position: 'bottom' }
}
}
});
JSFiddle: http://jsfiddle.net/kumilingus/trk63agg/
For more information please see the docs:
ports API
port layouts
Just change position name in your joint.shapes.devs.Model creation as follow:
new joint.shapes.devs.Model({
position: { x: x, y: y },
size: { width: 90, height: 90 },
inPorts: ['in1'],
outPorts:['out1'],
attrs: {
rect: { fill: '#2ECC71' },
'.inPorts circle': {r:10, fill: '#16A085' },
'.outPorts circle': { fill: '#E74C3C' }
},
ports: {
groups: {
'in': {
position: {
name: 'top'
},
attrs: {
'.port-body': {
r: 1
}
}
},
'out': {
position: {
name: 'bottom'
},
attrs: {
'.port-body': {
r: 1
}
}
}
}
}
});
Consider the position name changed to top and bottom