如何使用 cytoscape.js 保存和恢复复合节点的布局
How to save and restore layout of compound nodes using cytoscape.js
我正在使用 JavaScript 库 cytoscape.js 绘制一些拓扑图。
我可以使用以下代码片段来保存和恢复非复合节点情况下的布局。
<button id="save" class="button">save</button>
<button id="reload" class="button">reload</button>
document.getElementById("save").addEventListener("click", function(){
window.localStorage.setItem('savedlayout', JSON.stringify(cy.json()));
});
document.getElementById("reload").addEventListener("click", function(){
cy.json(JSON.parse(window.localStorage.getItem('savedlayout')));
});
此解决方案似乎不适用于复合节点的情况。我已经下载 some compound nodes demos 并尝试添加上面的代码片段,布局无法正确恢复。
请看我的演示。您可以拖动任何节点并单击 save
按钮,然后拖动一些节点并单击 restore
。
document.addEventListener('DOMContentLoaded', function(){
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
ready: function(){
this.nodes().forEach(function(node){
let width = [30, 70, 110];
let size = width[Math.floor(Math.random()*3)];
node.css("width", size);
node.css("height", size);
});
this.layout({name: 'cose-bilkent', animationDuration: 1000}).run();
},
style: [
{
selector: 'node',
style: {
'background-color': '#ad1a66'
}
},
{
selector: ':parent',
style: {
'background-opacity': 0.333
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ad1a66'
}
}
],
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:'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'} }
],
elements1: [{ 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', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n5'}},
{ group:'nodes', data:{ id: 'n6'}},
{ group:'nodes', data:{ id: 'n7', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n8', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n9', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n10', parent1: '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', parent1: 'n39'}},
{ group:'nodes', data:{ id: 'n25', parent1: 'n39'}},
{ group:'nodes', data:{ id: 'n26', parent1: 'n42'}},
{ group:'nodes', data:{ id: 'n27', parent1: 'n42'}},
{ group:'nodes', data:{ id: 'n28', parent1: 'n42'}},
{ group:'nodes', data:{ id: 'n29', parent1: 'n40'}},
{ group:'nodes', data:{ id: 'n31', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n32', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n33', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n34', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n35', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n36', parent1: 'n41'}},
{ 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: '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'} },
]
});
document.getElementById("layoutButton").addEventListener("click", function(){
var layout = cy.layout({
name: 'cose-bilkent',
animate: 'end',
animationEasing: 'ease-out',
animationDuration: 1000,
randomize: true
});
layout.run();
});
document.getElementById("randomize").addEventListener("click", function(){
var layout = cy.layout({
name: 'random',
animate: true,
animationDuration: 1000,
animationEasing: 'ease-out'
});
layout.run();
});
document.getElementById("save").addEventListener("click", function(){
window.localStorage.setItem('savedlayout', JSON.stringify(cy.json()));
});
document.getElementById("reload").addEventListener("click", function(){
cy.json(JSON.parse(window.localStorage.getItem('savedlayout')));
});
});
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 90%;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
button {
margin-right: 10px;
}
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!--polyfills are needed for this extension for old browsers like IE -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.5.7/shim.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-cose-bilkent/cytoscape-cose-bilkent.js"></script>
<button id="randomize" type="button">Randomize</button>
<button id="layoutButton" type="button">CoSE-Bilkent</button>
<button id="save" class="button">save</button>
<button id="reload" class="button">reload</button>
<div id="cy"></div>
编辑:
在@Ravenous 指出 cy.json():
的好处后,我又试了一次
在此示例中使用 cy.json()
效果很好,如果您在添加旧元素之前删除其他元素。
只要你运行预设布局,代码也可以是这样的:
document.getElementById("save").addEventListener("click", function () {
window.localStorage.setItem("elements", JSON.stringify( cy.json() ));
});
document.getElementById("reload").addEventListener("click", function () {
cy.elements().remove();
cy.json({ elements: JSON.parse( window.localStorage.getItem("elements") ).elements }).layout({ name: 'preset' }).run();
});
或
document.getElementById("save").addEventListener("click", function() {
window.localStorage.setItem("elements", JSON.stringify({
nodes: cy.nodes.jsons(),
edges: cy.edges.jsons()
}));
});
document.getElementById("reload").addEventListener("click", function() {
cy.elements().remove();
cy.add( JSON.parse(window.localStorage.getItem("elements")) ).layout({ name: 'preset' }).run();
});
旧答案:
这个问题已经被解决了,但是我花了一些时间才找到它。基本上,您需要使用 cy.nodes().jsons()
而不是 cy.json()
:
var elements = {
nodes: cy.nodes().jsons(),
edges: cy.edges().jsons(),
};
通过这种方式,您可以获得 JSON 格式的每个属性的集合。之后,您可以将 elements.json
保存到本地存储并通过 cy.add()
将它们放回图表中。我为图形添加了预设布局,这样位置在重新加载后不会混淆:
var elements1 = [{
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",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n5"
}
},
{
group: "nodes",
data: {
id: "n6"
}
},
{
group: "nodes",
data: {
id: "n7",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n8",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n9",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n10",
parent1: "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",
parent1: "n39"
}
},
{
group: "nodes",
data: {
id: "n25",
parent1: "n39"
}
},
{
group: "nodes",
data: {
id: "n26",
parent1: "n42"
}
},
{
group: "nodes",
data: {
id: "n27",
parent1: "n42"
}
},
{
group: "nodes",
data: {
id: "n28",
parent1: "n42"
}
},
{
group: "nodes",
data: {
id: "n29",
parent1: "n40"
}
},
{
group: "nodes",
data: {
id: "n31",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n32",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n33",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n34",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n35",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n36",
parent1: "n41"
}
},
{
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: "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"
}
}
];
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
ready: function() {
this.nodes().forEach(function(node) {
let width = [30, 70, 110];
let size = width[Math.floor(Math.random() * 3)];
node.css("width", size);
node.css("height", size);
});
this.layout({
name: "cose-bilkent",
animationDuration: 1000
}).run();
},
style: [{
selector: "node",
style: {
'content': 'data(id)',
'text-valign': 'center',
'text-halign': 'center',
'background-color': '#ad1a66'
}
},
{
selector: ":parent",
style: {
"background-opacity": 0.333
}
},
{
selector: "edge",
style: {
width: 3,
"line-color": "#ad1a66"
}
}
],
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: "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"
}
}
],
}));
document.getElementById("layoutButton").addEventListener("click", function() {
var layout = cy.layout({
name: "cose-bilkent",
animate: "end",
animationEasing: "ease-out",
animationDuration: 1000,
randomize: true
});
layout.run();
});
document.getElementById("randomize").addEventListener("click", function() {
var layout = cy.layout({
name: "random",
animate: true,
animationDuration: 1000,
animationEasing: "ease-out"
});
layout.run();
});
document.getElementById("save").addEventListener("click", function() {
window.localStorage.setItem("elements", JSON.stringify(cy.json()));
});
document.getElementById("reload").addEventListener("click", function() {
cy.elements().remove();
cy.json({
elements: JSON.parse(window.localStorage.getItem("elements")).elements
}).layout({
name: 'preset'
}).run();
cy.fit();
cy.center();
});
});
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
height: 100%;
width: 90%;
position: absolute;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
button {
margin-right: 10px;
}
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!--polyfills are needed for this extension for old browsers like IE -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.5.7/shim.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://cdn.jsdelivr.net/npm/cytoscape-cose-bilkent@4.1.0/cytoscape-cose-bilkent.min.js"></script>
<body>
<button id="randomize" type="button">Randomize</button>
<button id="layoutButton" type="button">CoSE-Bilkent</button>
<button id="save" class="button">save</button>
<button id="reload" class="button">reload</button>
<div id="cy"></div>
</body>
我正在使用 JavaScript 库 cytoscape.js 绘制一些拓扑图。
我可以使用以下代码片段来保存和恢复非复合节点情况下的布局。
<button id="save" class="button">save</button>
<button id="reload" class="button">reload</button>
document.getElementById("save").addEventListener("click", function(){
window.localStorage.setItem('savedlayout', JSON.stringify(cy.json()));
});
document.getElementById("reload").addEventListener("click", function(){
cy.json(JSON.parse(window.localStorage.getItem('savedlayout')));
});
此解决方案似乎不适用于复合节点的情况。我已经下载 some compound nodes demos 并尝试添加上面的代码片段,布局无法正确恢复。
请看我的演示。您可以拖动任何节点并单击 save
按钮,然后拖动一些节点并单击 restore
。
document.addEventListener('DOMContentLoaded', function(){
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
ready: function(){
this.nodes().forEach(function(node){
let width = [30, 70, 110];
let size = width[Math.floor(Math.random()*3)];
node.css("width", size);
node.css("height", size);
});
this.layout({name: 'cose-bilkent', animationDuration: 1000}).run();
},
style: [
{
selector: 'node',
style: {
'background-color': '#ad1a66'
}
},
{
selector: ':parent',
style: {
'background-opacity': 0.333
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ad1a66'
}
}
],
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:'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'} }
],
elements1: [{ 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', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n5'}},
{ group:'nodes', data:{ id: 'n6'}},
{ group:'nodes', data:{ id: 'n7', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n8', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n9', parent1: 'n37'}},
{ group:'nodes', data:{ id: 'n10', parent1: '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', parent1: 'n39'}},
{ group:'nodes', data:{ id: 'n25', parent1: 'n39'}},
{ group:'nodes', data:{ id: 'n26', parent1: 'n42'}},
{ group:'nodes', data:{ id: 'n27', parent1: 'n42'}},
{ group:'nodes', data:{ id: 'n28', parent1: 'n42'}},
{ group:'nodes', data:{ id: 'n29', parent1: 'n40'}},
{ group:'nodes', data:{ id: 'n31', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n32', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n33', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n34', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n35', parent1: 'n41'}},
{ group:'nodes', data:{ id: 'n36', parent1: 'n41'}},
{ 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: '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'} },
]
});
document.getElementById("layoutButton").addEventListener("click", function(){
var layout = cy.layout({
name: 'cose-bilkent',
animate: 'end',
animationEasing: 'ease-out',
animationDuration: 1000,
randomize: true
});
layout.run();
});
document.getElementById("randomize").addEventListener("click", function(){
var layout = cy.layout({
name: 'random',
animate: true,
animationDuration: 1000,
animationEasing: 'ease-out'
});
layout.run();
});
document.getElementById("save").addEventListener("click", function(){
window.localStorage.setItem('savedlayout', JSON.stringify(cy.json()));
});
document.getElementById("reload").addEventListener("click", function(){
cy.json(JSON.parse(window.localStorage.getItem('savedlayout')));
});
});
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 90%;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
button {
margin-right: 10px;
}
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!--polyfills are needed for this extension for old browsers like IE -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.5.7/shim.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-cose-bilkent/cytoscape-cose-bilkent.js"></script>
<button id="randomize" type="button">Randomize</button>
<button id="layoutButton" type="button">CoSE-Bilkent</button>
<button id="save" class="button">save</button>
<button id="reload" class="button">reload</button>
<div id="cy"></div>
编辑: 在@Ravenous 指出 cy.json():
的好处后,我又试了一次在此示例中使用 cy.json()
效果很好,如果您在添加旧元素之前删除其他元素。
只要你运行预设布局,代码也可以是这样的:
document.getElementById("save").addEventListener("click", function () {
window.localStorage.setItem("elements", JSON.stringify( cy.json() ));
});
document.getElementById("reload").addEventListener("click", function () {
cy.elements().remove();
cy.json({ elements: JSON.parse( window.localStorage.getItem("elements") ).elements }).layout({ name: 'preset' }).run();
});
或
document.getElementById("save").addEventListener("click", function() {
window.localStorage.setItem("elements", JSON.stringify({
nodes: cy.nodes.jsons(),
edges: cy.edges.jsons()
}));
});
document.getElementById("reload").addEventListener("click", function() {
cy.elements().remove();
cy.add( JSON.parse(window.localStorage.getItem("elements")) ).layout({ name: 'preset' }).run();
});
旧答案:
这个问题已经被解决了cy.nodes().jsons()
而不是 cy.json()
:
var elements = {
nodes: cy.nodes().jsons(),
edges: cy.edges().jsons(),
};
通过这种方式,您可以获得 JSON 格式的每个属性的集合。之后,您可以将 elements.json
保存到本地存储并通过 cy.add()
将它们放回图表中。我为图形添加了预设布局,这样位置在重新加载后不会混淆:
var elements1 = [{
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",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n5"
}
},
{
group: "nodes",
data: {
id: "n6"
}
},
{
group: "nodes",
data: {
id: "n7",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n8",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n9",
parent1: "n37"
}
},
{
group: "nodes",
data: {
id: "n10",
parent1: "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",
parent1: "n39"
}
},
{
group: "nodes",
data: {
id: "n25",
parent1: "n39"
}
},
{
group: "nodes",
data: {
id: "n26",
parent1: "n42"
}
},
{
group: "nodes",
data: {
id: "n27",
parent1: "n42"
}
},
{
group: "nodes",
data: {
id: "n28",
parent1: "n42"
}
},
{
group: "nodes",
data: {
id: "n29",
parent1: "n40"
}
},
{
group: "nodes",
data: {
id: "n31",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n32",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n33",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n34",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n35",
parent1: "n41"
}
},
{
group: "nodes",
data: {
id: "n36",
parent1: "n41"
}
},
{
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: "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"
}
}
];
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
ready: function() {
this.nodes().forEach(function(node) {
let width = [30, 70, 110];
let size = width[Math.floor(Math.random() * 3)];
node.css("width", size);
node.css("height", size);
});
this.layout({
name: "cose-bilkent",
animationDuration: 1000
}).run();
},
style: [{
selector: "node",
style: {
'content': 'data(id)',
'text-valign': 'center',
'text-halign': 'center',
'background-color': '#ad1a66'
}
},
{
selector: ":parent",
style: {
"background-opacity": 0.333
}
},
{
selector: "edge",
style: {
width: 3,
"line-color": "#ad1a66"
}
}
],
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: "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"
}
}
],
}));
document.getElementById("layoutButton").addEventListener("click", function() {
var layout = cy.layout({
name: "cose-bilkent",
animate: "end",
animationEasing: "ease-out",
animationDuration: 1000,
randomize: true
});
layout.run();
});
document.getElementById("randomize").addEventListener("click", function() {
var layout = cy.layout({
name: "random",
animate: true,
animationDuration: 1000,
animationEasing: "ease-out"
});
layout.run();
});
document.getElementById("save").addEventListener("click", function() {
window.localStorage.setItem("elements", JSON.stringify(cy.json()));
});
document.getElementById("reload").addEventListener("click", function() {
cy.elements().remove();
cy.json({
elements: JSON.parse(window.localStorage.getItem("elements")).elements
}).layout({
name: 'preset'
}).run();
cy.fit();
cy.center();
});
});
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
height: 100%;
width: 90%;
position: absolute;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
button {
margin-right: 10px;
}
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!--polyfills are needed for this extension for old browsers like IE -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.5.7/shim.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://cdn.jsdelivr.net/npm/cytoscape-cose-bilkent@4.1.0/cytoscape-cose-bilkent.min.js"></script>
<body>
<button id="randomize" type="button">Randomize</button>
<button id="layoutButton" type="button">CoSE-Bilkent</button>
<button id="save" class="button">save</button>
<button id="reload" class="button">reload</button>
<div id="cy"></div>
</body>