UNPKG

cytoscape-fcose

Version:

The fCoSE layout for Cytoscape.js by Bilkent with fast compound node placement

466 lines (420 loc) 23.4 kB
<!DOCTYPE> <html> <head> <title>cytoscape-fcose.js demo</title> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1"> <!-- Bootstrap, popper, jQuery and filesaver - for demo purpose only --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script> <script src="https://unpkg.com/layout-base/layout-base.js"></script> <script src="https://unpkg.com/cose-base/cose-base.js"></script> <script src="https://unpkg.com/cytoscape-layout-utilities/cytoscape-layout-utilities.js"></script> <!-- for testing with local version of cytoscape.js --> <!--<script src="../cytoscape.js/build/cytoscape.js"></script>--> <script src="../cytoscape-fcose.js"></script> <style> body { font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif; font-size: 14px; } #cy { position: relative; width: auto; height: 90%; z-index: 999; margin-left: 290px; right: 0px; } h1 { opacity: 1; color: #555; font-size: 15px; font-weight: bold; padding-top: 5px; } /* The sidepanel menu */ .sidepanel { height: auto; /* Specify a height */ width: 290px; /* 0 width - change this with JavaScript */ position: absolute; /* Stay in place */ z-index: 1000; /* Stay on top */ float: left; top: auto; left: 0; background-color: #b7ffff; /* Black*/ overflow-x: hidden; /* Disable horizontal scroll */ padding-top: 10px; /* Place content 10px from the top */ padding-bottom: 10px; /* Place content 10px from the bottom */ transition: 0s; /* 0.5 second transition effect to slide in the sidepanel */ } table{ margin-left: 4px; margin-right: auto; table-layout: fixed; } /* The sidepanel links */ table td { padding: 0px 8px 8px 8px; text-decoration: none; font-size: 13px; color: #555; transition: 0.3s; vertical-align: middle; } /* Style the button that is used to open the sidepanel */ .button { font-size: 15px; color: #555; cursor: pointer; background-color: #b7ffff; padding: 5px 10px; border: none; margin-bottom: 5px; } .textField { padding-left: 5px; } .checkbox { margin-left: 0px; } .button:hover { background-color: #0f0; } .btn-group-sm>.btn, .btn-sm { font-size: 13px; background-color: #7d8991; border-color: #7d8991; } .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open>.dropdown-toggle.btn-primary { color: #fff; background-color: #60717d; border-color: #60717d; /*set the color you want here*/ } .btn-outline-primary:hover, .btn-outline-primary:focus, .btn-outline-primary:active, .btn-outline-primary.active, .open>.dropdown-toggle.btn-primary { color: #fff; background-color: #60717d; border-color: #60717d; /*set the color you want here*/ } .form-control-sm { font-size: 13px } .custom-select-sm { font-size: 13px } .custom-control-label { padding-top: 2px; } .custom-control-input:checked~.custom-control-label::before { color: #fff; border-color: #7d8991; background-color: #7d8991; } </style> <script> document.addEventListener('DOMContentLoaded', function(){ var cy = window.cy = cytoscape({ container: document.getElementById('cy'), ready: function(){ let layoutUtilities = this.layoutUtilities({ desiredAspectRatio: this.width()/this.height() }); this.nodes().forEach(function(node){ let size = Math.random()*120+30; node.css("width", size); node.css("height", size); }); this.layout({name: 'fcose', animationEasing: 'ease-out'}).run(); }, // demo your layout layout: { name: 'grid' }, style: [ { selector: 'node', style: { 'background-color': '#2B65EC' } }, { selector: ':parent', style: { 'background-opacity': 0.333, 'border-color': '#2B65EC' } }, { selector: 'edge', style: { 'line-color': '#2B65EC' } }, { selector: 'node:selected', style: { 'background-color': '#F08080', 'border-color': 'red' } }, { selector: 'edge:selected', style: { 'line-color': '#F08080' } } ], elements: [{ group:'nodes', data:{ id: 'n0'}}, { group:'nodes', data:{ id: 'n1'}}, { group:'nodes', data:{ id: 'n2'}}, { group:'nodes', data:{ id: 'n3'}}, { group:'nodes', data:{ id: 'n4', parent: 'n37'}}, { group:'nodes', data:{ id: 'n5'}}, { group:'nodes', data:{ id: 'n6'}}, { group:'nodes', data:{ id: 'n7', parent: 'n37'}}, { group:'nodes', data:{ id: 'n8', parent: 'n37'}}, { group:'nodes', data:{ id: 'n9', parent: 'n37'}}, { group:'nodes', data:{ id: 'n10', parent: 'n38'}}, { group:'nodes', data:{ id: 'n12'}}, { group:'nodes', data:{ id: 'n13'}}, { group:'nodes', data:{ id: 'n14'}}, { group:'nodes', data:{ id: 'n15'}}, { group:'nodes', data:{ id: 'n16'}}, { group:'nodes', data:{ id: 'n17'}}, { group:'nodes', data:{ id: 'n18'}}, { group:'nodes', data:{ id: 'n19'}}, { group:'nodes', data:{ id: 'n20'}}, { group:'nodes', data:{ id: 'n21'}}, { group:'nodes', data:{ id: 'n22'}}, { group:'nodes', data:{ id: 'n23'}}, { group:'nodes', data:{ id: 'n24', parent: 'n39'}}, { group:'nodes', data:{ id: 'n25', parent: 'n39'}}, { group:'nodes', data:{ id: 'n26', parent: 'n42'}}, { group:'nodes', data:{ id: 'n27', parent: 'n42'}}, { group:'nodes', data:{ id: 'n28', parent: 'n42'}}, { group:'nodes', data:{ id: 'n29', parent: 'n40'}}, { group:'nodes', data:{ id: 'n31', parent: 'n41'}}, { group:'nodes', data:{ id: 'n32', parent: 'n41'}}, { group:'nodes', data:{ id: 'n33', parent: 'n41'}}, { group:'nodes', data:{ id: 'n34', parent: 'n41'}}, { group:'nodes', data:{ id: 'n35', parent: 'n41'}}, { group:'nodes', data:{ id: 'n36', parent: 'n41'}}, { group:'nodes', data:{ id: 'n37'}}, { group:'nodes', data:{ id: 'n38'}}, { group:'nodes', data:{ id: 'n39', parent: 'n43'}}, { group:'nodes', data:{ id: 'n40', parent: 'n42'}}, { group:'nodes', data:{ id: 'n41', parent: 'n42'}}, { group:'nodes', data:{ id: 'n42', parent: 'n43'}}, { group:'nodes', data:{ id: 'n43'}}, { group:'nodes', data:{ id: 'n44'}}, { group:'nodes', data:{ id: 'n45'}}, { group:'nodes', data:{ id: 'n46'}}, { group:'nodes', data:{ id: 'n47'}}, { group:'edges', data:{ id: 'e0', source: 'n0', target: 'n1'} }, { group:'edges', data:{ id: 'e1', source: 'n1', target: 'n2'} }, { group:'edges', data:{ id: 'e2', source: 'n2', target: 'n3'} }, { group:'edges', data:{ id: 'e3', source: 'n0', target: 'n3'} }, { group:'edges', data:{ id: 'e4', source: 'n1', target: 'n4'} }, { group:'edges', data:{ id: 'e5', source: 'n2', target: 'n4'} }, { group:'edges', data:{ id: 'e6', source: 'n4', target: 'n5'} }, { group:'edges', data:{ id: 'e7', source: 'n5', target: 'n6'} }, { group:'edges', data:{ id: 'e8', source: 'n4', target: 'n6'} }, { group:'edges', data:{ id: 'e9', source: 'n4', target: 'n7'} }, { group:'edges', data:{ id: 'e10', source: 'n7', target: 'n8'} }, { group:'edges', data:{ id: 'e11', source: 'n8', target: 'n9'} }, { group:'edges', data:{ id: 'e12', source: 'n7', target: 'n9'} }, { group:'edges', data:{ id: 'e13', source: 'n13', target: 'n14'} }, //{ group:'edges', data:{ id: 'e14', source: 'n12', target: 'n14'} }, { group:'edges', data:{ id: 'e15', source: 'n14', target: 'n15'} }, { group:'edges', data:{ id: 'e16', source: 'n14', target: 'n16'} }, { group:'edges', data:{ id: 'e17', source: 'n15', target: 'n17'} }, { group:'edges', data:{ id: 'e18', source: 'n17', target: 'n18'} }, { group:'edges', data:{ id: 'e19', source: 'n18', target: 'n19'} }, { group:'edges', data:{ id: 'e20', source: 'n17', target: 'n20'} }, { group:'edges', data:{ id: 'e21', source: 'n19', target: 'n20'} }, { group:'edges', data:{ id: 'e22', source: 'n16', target: 'n20'} }, { group:'edges', data:{ id: 'e23', source: 'n20', target: 'n21'} }, { group:'edges', data:{ id: 'e25', source: 'n23', target: 'n24'} }, { group:'edges', data:{ id: 'e26', source: 'n24', target: 'n25'} }, { group:'edges', data:{ id: 'e27', source: 'n26', target: 'n38'} }, { group:'edges', data:{ id: 'e29', source: 'n26', target: 'n39'} }, { group:'edges', data:{ id: 'e30', source: 'n26', target: 'n27'} }, { group:'edges', data:{ id: 'e31', source: 'n26', target: 'n28'} }, { group:'edges', data:{ id: 'e33', source: 'n21', target: 'n31'} }, { group:'edges', data:{ id: 'e35', source: 'n31', target: 'n33'} }, { group:'edges', data:{ id: 'e36', source: 'n31', target: 'n34'} }, { group:'edges', data:{ id: 'e37', source: 'n33', target: 'n34'} }, { group:'edges', data:{ id: 'e38', source: 'n32', target: 'n35'} }, { group:'edges', data:{ id: 'e39', source: 'n32', target: 'n36'} }, { group:'edges', data:{ id: 'e40', source: 'n16', target: 'n40'} }, { group:'edges', data:{ id: 'e41', source: 'n44', target: 'n45'} }, { group:'edges', data:{ id: 'e42', source: 'n44', target: 'n46'} }, { group:'edges', data:{ id: 'e43', source: 'n45', target: 'n46'} } ] }); document.getElementById("randomizeButton").addEventListener("click", function(){ var layout = cy.layout({ name: 'random', animate: true, animationDuration: 1000 }); layout.run(); }); document.getElementById("fcoseButton").addEventListener("click", function(){ let qualityItem = document.getElementById("quality"); var layout = cy.layout({ name: 'fcose', quality: qualityItem.options[qualityItem.selectedIndex].value, randomize: !(document.getElementById("randomize").checked), animate: document.getElementById("animate").checked, animationEasing: 'ease-out', fit: document.getElementById("fit").checked, uniformNodeDimensions: document.getElementById("uniformNodeDimensions").checked, packComponents: document.getElementById("packComponents").checked, tile: document.getElementById("tile").checked, nodeRepulsion: parseFloat(document.getElementById("nodeRepulsion").value), idealEdgeLength: parseFloat(document.getElementById("idealEdgeLength").value), edgeElasticity: parseFloat(document.getElementById("edgeElasticity").value), nestingFactor: parseFloat(document.getElementById("nestingFactor").value), gravity: parseFloat(document.getElementById("gravity").value), gravityRange: parseFloat(document.getElementById("gravityRange").value), gravityCompound: parseFloat(document.getElementById("gravityCompound").value), gravityRangeCompound: parseFloat(document.getElementById("gravityRangeCompound").value), numIter: parseFloat(document.getElementById("numIter").value), tilingPaddingVertical: parseFloat(document.getElementById("tilingPaddingVertical").value), tilingPaddingHorizontal: parseFloat(document.getElementById("tilingPaddingHorizontal").value), initialEnergyOnIncremental: document.getElementById("initialEnergyOnIncremental").value, step:"all" }); layout.run(); }); }); </script> </head> <body> <h1 class="ml-2">cytoscape-fcose demo (compound)</h1> <div style='width: 300px; position: absolute;'> <button id="randomizeButton" class="btn btn-primary btn-sm mb-2 ml-2">Randomize</button>&nbsp &nbsp <button id="fcoseButton" class="btn btn-primary btn-sm mb-2 ml-2">fCoSE</button> <div id="mySidepanel" class="sidepanel"> <table> <tr> <td><span class="add-on layout-text" title="Quality of the layout"> Quality </span></td> <td> <select id="quality" class='custom-select custom-select-sm'> <option value="draft">draft</option> <option value="default" selected="">default</option> <option value="proof">proof</option> </select> </td> </tr> <tr> <td><span class="add-on layout-text" title="Whether to enable incremental mode"> Incremental </span></td> <td> <div class="custom-control custom-control-inline custom-checkbox"> <input type="checkbox" class="custom-control-input" id="randomize" name="incremental"> <label class="custom-control-label" for="randomize"></label> </div> </td> </tr> <tr> <td><span class="add-on layout-text" title="Whether to perform animation after layout"> Animate </span></td> <td> <div class="custom-control custom-control-inline custom-checkbox"> <input type="checkbox" class="custom-control-input" id="animate" name="animate" checked> <label class="custom-control-label" for="animate"></label> </div> </td> </tr> <tr> <td><span class="add-on layout-text" title="Whether to fit the viewport to the repositioned nodes"> Fit </span></td> <td> <div class="custom-control custom-control-inline custom-checkbox"> <input type="checkbox" class="custom-control-input" id="fit" name="fit" checked> <label class="custom-control-label" for="fit"></label> </div> </td> </tr> <tr> <td><span class="add-on layout-text" title="Whether nodes are of uniform dimensions"> Uniform Node Dimensions </span></td> <td> <div class="custom-control custom-control-inline custom-checkbox"> <input type="checkbox" class="custom-control-input" id="uniformNodeDimensions" name="uniformNodeDimensions"> <label class="custom-control-label" for="uniformNodeDimensions"></label> </div> </td> </tr> <tr> <td><span class="add-on layout-text" title="Whether to pack components"> Pack Components to Window </span></td> <td> <div class="custom-control custom-control-inline custom-checkbox"> <input type="checkbox" class="custom-control-input" id="packComponents" name="packComponents" checked> <label class="custom-control-label" for="packComponents"></label> </div> </td> </tr> <tr> <td><span class="add-on layout-text" title="Whether to tile disconnected nodes"> Tile Disconnected </span></td> <td> <div class="custom-control custom-control-inline custom-checkbox"> <input type="checkbox" class="custom-control-input" id="tile" name="tile" checked> <label class="custom-control-label" for="tile"></label> </div> </td> </tr> <tr> <td><span class="add-on layout-text" title="Node repulsion (non overlapping) multiplier"> Node Repulsion </span></td> <td><input id="nodeRepulsion" class="textField form-control form-control-sm" type="text" value="4500" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Ideal (intra-graph) edge length"> Ideal Edge Length </span></td> <td><input id="idealEdgeLength" class="textField form-control form-control-sm" type="text" value="50" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Divisor to compute edge forces"> Edge Elasticity </span></td> <td><input id="edgeElasticity" class="textField form-control form-control-sm" type="text" value="0.45" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Nesting factor (multiplier) to compute ideal edge length for inter-graph edges"> Nesting Factor </span></td> <td><input id="nestingFactor" class="textField form-control form-control-sm" type="text" value="0.1" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Gravity force (constant)"> Gravity </span></td> <td><input id="gravity" class="textField form-control form-control-sm" type="text" value="0.25" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Gravity range (constant)"> Gravity Range </span></td> <td><input id="gravityRange" class="textField form-control form-control-sm" type="text" value="3.8" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Gravity force (constant) for compounds"> Compound Gravity </span></td> <td><input id="gravityCompound" class="textField form-control form-control-sm" type="text" value="1" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Gravity range (constant) for compounds"> Compound Gravity Range </span></td> <td><input id="gravityRangeCompound" class="textField form-control form-control-sm" type="text" value="1.5" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Maximum number of iterations to perform"> Number of Iterations </span></td> <td><input id="numIter" class="textField form-control form-control-sm" type="text" value="2500" size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Amount of vertical space to put between degree zero nodes during tiling"> Tiling Vertical Padding </span></td> <td><input id="tilingPaddingVertical" class="textField form-control form-control-sm" type="text" value="10" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Amount of horizontal space to put between degree zero nodes during tiling"> Tiling Horizontal Padding </span></td> <td><input id="tilingPaddingHorizontal" class="textField form-control form-control-sm" type="text" value="10" maxlength=5 size="5"></td> </tr> <tr> <td><span class="add-on layout-text" title="Initial cooling factor for incremental layout"> Incremental Cooling Factor </span></td> <td><input id="initialEnergyOnIncremental" class="textField form-control form-control-sm" type="text" value="0.3" maxlength=5 size="5"></td> </tr> </table> </div> </div> <div id="cy"></div> </body> </html>