My objective is to programmatically draw a static diagram following a set of constraints (provided externally) and save that graphic to a file (in, say, PNG format). I have written code to read a graph in GML format and produce the Cytoscape output. The file I produced displays the graph successfully. (I don't see a way to attach the file.) Following tutorial examples, I have created an html file on Windows 11 and added cytoscape.min.js into the same folder to display it. Here is a snapshot of part of the graph. Portion of my graph 109. I want to make many changes to this graph, but for this question I'll focus on the following changes to the graph:
I have previously edited the specification of a node, adding a style section to that node, specifying its width:
{ data: { id: '1', name: 'Party' }, position: {x: 412.000000,y: 512.000000 }, style: { 'width' : '200.000000'}},
I read on this site: https://js.cytoscape.org/#style/edge-endpoints about Edge endpoints. I tried editing the html file, adding a style section to the edge in question. When I double-clicked on the resulting file I was shown a blank page. How, then, can I accomplish this?
Original: { data: { id: '2-13', source: '2', target:'13' } },
Changed to:
{
data: {
id: '2-13',
source: '2',
target:'13'
},
style: {
source-endpoint: '90deg'
}
},
EDIT BEGINS HERE
Here is a simple cytoscape diagram. Diagram showing AssetTp(top),and UoM(right)
Something like this code snippet is what I want to add to the above file (after the Cytoscape json is defined, and before the end-of-script line. It shows how I have hoped I would be able to position individual edges. Here is the html/css/js file used to create that diagram:
var cy = cytoscape({
container: document.getElementById('cy'),
elements: [{
data: {
id: '2',
name: 'AssetTp'
},
position: {
x: 212.000000,
y: 212.000000
},
style: {
'width': '400.000000'
}
},
{
data: {
id: '13',
name: 'CLnItm'
},
position: {
x: 112.000000,
y: 312.000000
}
},
{
data: {
id: '8',
name: 'UoM'
},
position: {
x: 312.000000,
y: 412.000000
}
},
{
data: {
id: '2-8',
source: '2',
target: '8'
}
},
{
data: {
id: '2-13',
source: '2',
target: '13'
}
}
],
style: [{
selector: 'node',
style: {
'text-valign': 'center',
'shape': 'rectangle',
'text-halign': 'center',
'font-size': '12',
'width': '60',
'label': 'data(name)'
}
},
{
selector: 'edge',
style: {
'width': 2,
'line-color': 'black',
'target-arrow-color': 'black',
'curve-style': 'bezier',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'preset'
}
});
/*
I want to set the edge ('2-8') between
AssetTp(2) and UoM(8) to be vertical.
This is my draft to show my intent.
This is hard-coded for simplicity--these
calculations would of course be performed
in a function.
There are likely many syntax errors.
*/
let e28 = cy.$('#2-8');
// Get that edge's target node's bounding box
let tbbox = e28.target().boundingBox();
// Get that edge's current target endpoint
let e28TargetPos = e28.targetEndpoint();
// Calculate the edge's new target coordinates
let e28TargetX = tbbox.x1 + (tbbox.w / 2);
let e28TargetY = e28TargetPos.y;
// Following the same pattern, get the source node details
let sbbox = e28.source().boundingBox();
let e28SourcePos = e28.sourceEndpoint();
/* Calculate the new source coordinates
Position the edge's source x coordinate directly above
its target x coordinate.
*/
let e28SourceX = e28TargetX;
let e28SourceY = e28SourcePos.y;
// The heart of my question: how to assign these new
// values to edge e28? This next line is entirely speculative.
// e28Pos.set(e28SourceX, e28SourceY, e28TargetX, e28TargetY);
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<!doctype html>
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
Moving edges is, as far as I know, not possible. The edges always point to a node, so moving the node is the way to go. Removing an edge and adding a new one won't change the position of the node. I added an MRE showing you a way to move a node (and subsequently the connected edge(s):
// get the source and target node
let AssetTp = cy.$('#2');
let CLnltm = cy.$('#13');
// calculate the desired position based off the nodes
let xPos = AssetTp.boundingBox().x1 + (AssetTp.width() / 2);
let yPos = CLnltm.position('y');
// move the target node with .animate()
CLnltm.animate(
{ position: { x: xPos, y: yPos } },
{ duration: 1000 },
);
Here is the working MRE:
var cy = cytoscape({
container: document.getElementById('cy'),
elements: [{
data: {
id: '2',
name: 'AssetTp'
},
position: {
x: 212.000000,
y: 212.000000
},
style: {
'width': '400.000000'
}
},
{
data: {
id: '13',
name: 'CLnItm'
},
position: {
x: 112.000000,
y: 312.000000
}
},
{
data: {
id: '8',
name: 'UoM'
},
position: {
x: 312.000000,
y: 412.000000
}
},
{
data: {
id: '2-8',
source: '2',
target: '8'
}
},
{
data: {
id: '2-13',
source: '2',
target: '13'
}
}
],
style: [{
selector: 'node',
style: {
'text-valign': 'center',
'shape': 'rectangle',
'text-halign': 'center',
'font-size': '12',
'width': '60',
'label': 'data(name)'
}
},
{
selector: 'edge',
style: {
'width': 2,
'line-color': 'black',
'target-arrow-color': 'black',
'curve-style': 'bezier',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'preset'
}
});
cy.off('layoutready');
cy.ready(() => {
let AssetTp = cy.$('#2');
let CLnltm = cy.$('#13');
let xPos = AssetTp.boundingBox().x1 + (AssetTp.width() / 2);
let yPos = CLnltm.position('y');
CLnltm.animate({
position: {
x: xPos,
y: yPos,
},
}, {
duration: 1000,
});
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<!doctype html>
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>