CoSE-Bilkent Layout for Cytoscape.js
Cytoscape-cose-bilkent provides an advanced Compound Spring Embedder (CoSE) layout algorithm for the Cytoscape.js graph visualization library. Developed by the i-Vis Lab at Bilkent University, it is specifically designed to handle complex compound graphs with nested structures and supports non-uniform node dimensions, which is a key differentiator from simpler layout algorithms. The current stable version is 4.1.0. The package has seen performance improvements (e.g., v3.0.0) and architectural changes (v4.1.0) for better modularity. It maintains an active release cadence, primarily focusing on compatibility with Cytoscape.js and continuous improvements to its layout quality and speed. Its primary purpose is to produce aesthetically pleasing and readable layouts for graphs, particularly those with hierarchical or grouped components, by intelligently managing node repulsion, edge elasticity, and gravitational forces.
Common errors
-
TypeError: cytoscape.use is not a function
cause Attempting to register the layout extension before Cytoscape.js itself has been properly loaded or initialized.fixEnsure `cytoscape` is fully imported and available before calling `cytoscape.use(coseBilkent)`. -
Layout 'cose-bilkent' could not be found
cause The `cose-bilkent` extension was not correctly registered with Cytoscape.js using `cytoscape.use(coseBilkent);` or the layout name was misspelled.fixVerify that `import coseBilkent from 'cytoscape-cose-bilkent';` and `cytoscape.use(coseBilkent);` are present and executed before attempting to use the layout, and ensure `name: 'cose-bilkent'` is used in the layout call. -
Cannot read properties of undefined (reading 'layout')
cause This usually indicates that the Cytoscape.js instance (`cy`) has not been properly initialized or is not yet available when the layout is attempted to be applied.fixEnsure `const cy = cytoscape({...});` has completed execution and `cy` is a valid Cytoscape.js graph instance before calling `cy.layout()`.
Warnings
- breaking Version 4.0.0 introduced a breaking change, requiring Cytoscape.js version `^3.2.0` or newer. Older Cytoscape.js versions are no longer supported.
- breaking Version 4.1.0 refactored core logic into new external packages (`cose-base` and `layout-base`). While npm installations handle these dependencies automatically, users integrating via direct HTML/JS file inclusion will need to manually source and include `cose-base` and `layout-base` script files *before* `cytoscape-cose-bilkent`.
- gotcha This extension primarily targets modern browsers. Legacy browsers like Internet Explorer may require significant polyfilling (e.g., with `core-js`) to function correctly, due to reliance on modern JavaScript features.
- gotcha The layout options significantly impact visual quality and performance. Default options might not be optimal for all graph sizes or structures, potentially leading to slow layouts or undesirable arrangements.
Install
-
npm install cytoscape-cose-bilkent -
yarn add cytoscape-cose-bilkent -
pnpm add cytoscape-cose-bilkent
Imports
- coseBilkent
import { coseBilkent } from 'cytoscape-cose-bilkent';import coseBilkent from 'cytoscape-cose-bilkent'; cytoscape.use(coseBilkent);
- coseBilkent (CommonJS)
require('cytoscape-cose-bilkent')();const coseBilkent = require('cytoscape-cose-bilkent'); cytoscape.use(coseBilkent); - cy.layout({ name: 'cose-bilkent' })
cy.layout({ name: 'cose', ...options }).run();cy.layout({ name: 'cose-bilkent', ...options }).run();
Quickstart
import cytoscape from 'cytoscape';
import coseBilkent from 'cytoscape-cose-bilkent';
// Register the cose-bilkent layout extension with Cytoscape.js
cytoscape.use(coseBilkent);
const cy = cytoscape({
container: document.getElementById('cy'), // Assumes a div with id='cy' exists
elements: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'c' } },
{ data: { id: 'parent1' } },
{ data: { id: 'd', parent: 'parent1' } },
{ data: { id: 'e', parent: 'parent1' } },
{ data: { id: 'f' } },
{ data: { id: 'ab', source: 'a', target: 'b' } },
{ data: { id: 'ac', source: 'a', target: 'c' } },
{ data: { id: 'ce', source: 'c', target: 'e' } },
{ data: { id: 'df', source: 'd', target: 'f' } },
],
style: [
{
selector: 'node',
style: {
'background-color': '#11479e',
'label': 'data(id)',
},
},
{
selector: 'node:parent',
style: {
'background-opacity': 0.3,
'background-color': '#ccc',
},
},
{
selector: 'edge',
style: {
'width': 4,
'line-color': '#9dbaea',
'target-arrow-color': '#9dbaea',
'target-arrow-shape': 'triangle',
'curve-style': 'bezier',
},
},
],
layout: {
name: 'preset' // Initial layout, will be overridden by cose-bilkent
}
});
// Apply the cose-bilkent layout
cy.layout({
name: 'cose-bilkent',
nodeDimensionsIncludeLabels: true,
fit: true,
padding: 20,
randomize: true,
nodeRepulsion: 4500,
idealEdgeLength: 50,
edgeElasticity: 0.45,
nestingFactor: 0.1,
gravity: 0.25,
numIter: 2500,
tile: true,
animate: 'end',
animationDuration: 500,
quality: 'default' // 'draft', 'default', 'proof'
}).run();