Thanks in advance for the answers and to authors for the cytoscape.js library.
For some purposes, one type (an algorithm) of layout is enough. But sometimes it is very handy to use different layouts for subgraphs or independent graphs on the same viewport.
I hope that I just doing wrong with layouts. I have some questions because I didn't find a way or I can't understand how it works in cytoscapejs. But I believe in the framework.
- Let's think here are 2 problems a) two disconnected graphs b) two subgraphs with 1 common root (to simplify it)
- Is it possible to apply different layout algorithms to graphs or subgraphs to automatically avoid overlapping of these groups of nodes etc?
In the documentation I see the statement "compound nodes are treated just like regular nodes". I hope that compound nodes are used in layout() they will be arranged the same way as simple nodes. It means for me that I can apply a layout to groups of nodes that are some compounds. This way gives me i.e. two or more sets of compound groups with different layouts each one. And I hope to see a correct arrangement.
Small note about documentation. It is not clear what the layout in the CytoscapeJS is and how they are arranged if viewport has 2 and more layouts. Yes, there are examples how to assign selected nodes to layout. But how layouts will be arranged? The same question about ele, eles and etc. In my point of view it is not clear is it alias or object to be used in a function? Is eles/ele require declaration as cy = cytoscape({...}) ? I supposed that layouts are arranged as it is defined in "main" layout(name:"") related to html container "cy". There are groups of nodes or subgraphs with own layouts.
I tried grouped nodes and compounded nodes with different layouts but they are overlapped.
The best I did were 3 layouts for 3 groups of nodes. No boundaryBox settings. The layouts are overlapped.
<script>
var cy = cytoscape({
container: document.getElementById('cy'),
elements: {
nodes: [
{ data: { id: 'para' } },
{ data: { group: 'ga', id: 'a', parent: 'para' } },
{ data: { group: 'ga', id: 'a1', parent: 'para' } },
{ data: { group: 'ga', id: 'a2', parent: 'para' } },
{ data: { group: 'ga', id: 'a3', parent: 'para' } },
{ data: { group: 'ga', id: 'a4', parent: 'para' } },
{ data: { id: 'parb' } },
{ data: { group: 'gb', id: 'b', parent: 'parb' } },
{ data: { group: 'gb', id: 'b1', parent: 'parb' } },
{ data: { group: 'gb', id: 'b2', parent: 'parb' } },
{ data: { group: 'gb', id: 'b3', parent: 'parb' } },
{ data: { group: 'gb', id: 'b4', parent: 'parb' } },
{ data: { group: 'gb', id: 'b5', parent: 'parb' } },
{ data: { id: 'parc' } },
{ data: { group: 'gc', id: 'c', parent: 'parc' } },
{ data: { group: 'gc', id: 'c1', parent: 'parc' } },
{ data: { group: 'gc', id: 'c2', parent: 'parc' } },
{ data: { group: 'gc', id: 'c3', parent: 'parc' } },
],
edges: [
{ data: { id: 'ab', source: 'a', target: 'b'} },
{ data: { id: 'bc', source: 'b', target: 'c'} },
{ data: { id: 'a-c1', source: 'a', target: 'a1'} },
{ data: { id: 'a-c2', source: 'a', target: 'a2'} },
{ data: { id: 'a-c3', source: 'a', target: 'a3'} },
{ data: { id: 'a-c4', source: 'a', target: 'a4'} },
{ data: { id: 'b-c1', source: 'b', target: 'b1'} },
{ data: { id: 'b-c2', source: 'b', target: 'b2'} },
{ data: { id: 'b-c3', source: 'b', target: 'b3'} },
{ data: { id: 'b-c4', source: 'b', target: 'b4'} },
{ data: { id: 'b-c5', source: 'b', target: 'b5'} },
{ data: { id: 'c-c1', source: 'c', target: 'c1'} },
{ data: { id: 'c-c2', source: 'c', target: 'c2'} },
{ data: { id: 'c-c3', source: 'c', target: 'c3'} },
]
},
style: [
{
selector: 'node',
style: {
shape: 'hexagon',
'background-color': '#b0e0f0',
label: 'data(id)'
}
}]
});
cy.layout({name: 'cose-bilkent'});
cy.$('#para').style({ 'background-color': '#ffa050', 'background-opacity':0.1 })
cy.$('#parb').style({ 'background-color': 'green', 'background-opacity':0.1 })
cy.$('#parc').style({ 'background-color': 'cyan', 'background-opacity':0.1 })
var as = cy.$('#a1,#a2,#a3,#a4');
as.style({ 'background-color': '#ffa050', 'background-opacity':0.76 })
var bs = cy.$('#b1,#b2,#b3,#b4,#b5');
bs.style({ 'background-color': 'lightgreen', 'background-opacity':0.5 })
var cs = cy.$('#c,#c1,#c2,#c3');
cs.style({ 'background-color': '#b0e0f0', 'background-opacity':1 })
var al = as.nodes().layout({name:'grid' })//.run()
var bl = bs.nodes().layout({name:'circle' })//.run()
var cl = cs.nodes().layout({name:'breadthfirst' })//.run()
al.run()
bl.run()
cl.run()
</script>
The logic I believe is something about the nested or clustered approach:
a) every group with own layout properties is calculated and has its own parameters about used space to be set to a boundaryBox;
b) after that the boundaryBoxes are arranged in a similar way as nodes because they are the same entity - it is some object taking a space;
c) it could be done as nested logic working from the deepest bottom level to the upper while it is done;
The question is: How to set different layouts to groups of nodes and avoid layouts overlapping?
With best regards, Alex