Cytoscape disappearing edges with bezier curves and nodes moving/longer labels in nodes - cytoscape.js

I am using cytoscape with bezier curves but edges are disappearing when having a node with longer label or just moving source node next to target node.
Video: https://www.screencast.com/t/N2f5eZ5M7
Runnable sample: https://stackblitz.com/edit/web-platform-vpl72r?file=index.html
I have already seen "Edge xxxxx has invalid endpoints and so it is impossible to draw" warning and searched corresponding threads but couldn't find a solution.
Does anyone know how to handle that ?

I see some warnings on the console
The style value of label is deprecated for width
The style value of label is deprecated for height
After I deleted 'width': 'label', 'height':'label', I no longer observe such problem.
--- Update 1.1 ---
but I'd like to have node's dimensions based on label's dimensions.
To do this I think you should write a function style. See the below example. In the example, you can see that we are setting the size of the nodes dynamically based on their name length. I assumed name is a string that stores labels.
cy.style().selector('node').style({
'width': (x) => { return x.data('name').length + 'px;' }
'height': (x) => { return x.data('name').length + 'px;' }
}).update();

Related

Cytoscape JS CoSe Layout Label Length Effect

I made an observation with Cytoscape Layout and I am wondering how to change it. The layout manager CoSe produces different results depending on the length of the label name. I encountered this when I changed the node label from a long to a short id and also to no id. The best result is produced with no id.
How to deactivate this label layout effect ?
There is a planned feature to specify how the bounding box is calculated for nodes in a layout: https://github.com/cytoscape/cytoscape.js/issues/1626
Before that's implemented, you'll have to hide labels while the layout is running.
E.g.
cy.nodes().addClass('no-labels');
cy.one('layoutstop', () => cy.nodes().removeClass('no-labels'));
cy.makeLayout({ ... }).run();
Where node.no-labels { label: '' } is defined in your stylesheet.

Sizing Node Relative to Label in cytoscape

So I'm aware you can use a function to compute a css property in Cytoscape.js e.g.
cytoscape.stylesheet()
.selector('node')
.css({
'width': function(ele) {
return 12;
})
I'm also aware of the special value 'label' that can be the value of the property e.g.
cytoscape.stylesheet()
.selector('node')
.css({
'width': 'label'
})
What I'm wondering is is there any particular property I could use to scale the label by some factor, e.g. what I want is something like
cytoscape.stylesheet()
.selector('node')
.css({
'width': function(ele) {
return labelWidth * 1.5; //Where to get labelWidth from
})
Specially I want the ability to be able to calculate the height and width of an ellipse so that the label is completely contained within the ellipse (which can be computed using some math e.g. Ellipse bounding a rectangle).
But I haven't been able to find a way to get the labelWidth. I did manage to do it using rscratch but only if the node actually got rendered twice (e.g. multiple .selectors), any proper way to get the label width and height from a given element (or at least a way to calculate how it'll be rendered?).
If you want to do more sophisticated sizing, your calculations are going to have to be more sophisticated.
Options :
(1) Calculate the dimensions of the text yourself using a div.
(2) Use the auto sizing, and then adjust the size based on the current size.
(1) is cleaner than (2).
It doesn't make sense for Cytoscape.js to expose rendered calculated values for you in the stylesheet. Those values are calculated from the stylesheet, creating a dependency cycle.
If you just want the label inside your node, you could just set the padding attribute to make more space around the text.

Circle layout with custom center coordinates

I'm building a dynamic graph with cytoscape.js over a world map generated with jVectorMap.
Starting with coordinates in LAT / LON format from json data, I can convert them in point.x / point.y over the generated map with:
var nodePoint = theMap.latLngToPoint(node.data.lat, node.data.lon)
and then I can add the new node in the graph with:
cy.add({
group: "nodes",
position: { x: nodePoint.x, y: nodePoint.y },
style: {
'background-color': node.color
},
data: {
id: node.id,
name: node.label,
customData: node.data,
}
})
This part works, but when json returns multiple nodes with the same coordinates, I would like to spread these nodes around the point with the common LAT / LON information.
I'm able to identify these nodes and apply a dedicated layout to them, but the resulting layount is located in the center of the screen / div of graph.
What I want to know is if there is a simple way to apply a Circle Layout with specific center point.
(I would like to avoid implementing the solution that I'm evaluating... i.e to build a bounding box around the center point and see what happens, (with the bounding box size that grows along with node number in the same point))
In the Wine and cheese example included in the documentation they use the bounding box to force a concentric layout around a selected node ( http://js.cytoscape.org/demos/cde4db55e581d10405f5/ ).
While you indicate you would like to avoid this solution it seems a straightforward solution. The implementation in the example is rather elegant.

Adding image as a label on edge in cytoscape.js

Created a graph using cytoscape.js. Need to add image as a label on edge.
After examination of
CanvasRenderer.drawElements in https://github.com/cytoscape/cytoscape.js/blob/v2.3.8/src/extensions/renderer.canvas.drawing-redraw.js#L406-L412
CanvasRenderer.drawEdgeText in https://github.com/cytoscape/cytoscape.js/blob/v2.3.8/src/extensions/renderer.canvas.drawing-label-text.js#L6-L31
CanvasRenderer.drawEdge in https://github.com/cytoscape/cytoscape.js/blob/v2.3.8/src/extensions/renderer.canvas.drawing-edges.js
it seems that image label on edge is not supported right now.
One candidate where this feature might be added seems to be the CanvasRenderer.drawEdgeText function. The implementation might examine the text contained in the edge's content and if it looks like reference to an image (e.g. url) then draw it as image...
https://github.com/cytoscape/cytoscape.js/blob/v2.3.8/README.md
Contributing to Cytoscape.js
Cytoscape.js is an open source project, and anyone interested is encouraged to contribute to Cytoscape.js. We gladly accept pull requests. If you are interested in regular contributions to Cytoscape.js, then we can arrange granting you permission to the repository by contacting us.
If your pull request is a bugfix, please make changes to the master branch. Otherwise, please make changes to the next version's branch (i.e. unstable).
I know this is a late answer. but this will help somebody who looks for an answer as like me.
We can use icon fonts or fontawesome for this.
set the edges data as
edges = {
data:
id: "3f5cb5c4-43aa-4f4d-b816-fb4f279585c7"
label: "1 A \uf023 \uf022" //this is the fontawesome unicode chars for lock and notes icons
source: "1"
sourceName: "shipping"
target: "4"
targetName: "twilio.com"
value: 2
}
next in your cytoscape style, mention the font as fontawesome
{
selector: '.autorotate',
style: {
'edge-text-rotation': 'autorotate',
'font-size': '8px',
// 'color': '#000000',
'color': '#333333',
'font-family': 'FontAwesome, helvetica neue Cantarell',
'text-margin-x':'5px',
'text-margin-y':'5px',
// 'source-text-margin-x':'5px',
// 'source-text-margin-y':'5px'
}
}
Now your cytoscape graph will show edges with images as like this

how to set distance between cells in grid in cytoscape js?

I made a graph in cytoscape js using a grid layout and I specified the row and col for each node.
However the graph being rendered is very zoomed out and the spacing between the nodes is very large. I fixed this problem partially by specifying the number of rows and columns for the grid layout (see picture. Although specifying the number of rows and columns is not desired as the size of the graph can change.
The resulting graph (when specifying the rows and columns) is still not optimum, the nodes are still rendered too small and the distance between them horizontally is still quite large.
Is there anyway to specify the distance between the grid cells?
My current code for the grid layout looks as follows:
layout: {
name: 'grid',
padding: 30,
rows: 20,
columns: 10,
fit: true,
position: function( node ){ return {row:node.data('row'), col:node.data('col')}; }
}
The grid layout automatically uses the dimensions of your nodes and the available space to position the nodes in the graph. If you're looking for new functionality, please file an issue describing the feature you would like.
Thanks for using Cytoscape.js.
It maybe filthy hack, but it works for me.
Just find function in cytoscape code for grid layout:
GridLayout.prototype.run
In this function find lines like:
var cellWidth = bb.w / cols;
var cellHeight = bb.h / rows;
Just add some multipliers to cellWidth and cellHeight, like below:
var cellWidth = bb.w / cols * 2.5;
var cellHeight = bb.h / rows / 4;
Also you can extract multipliers like layout params.