I want to make a network graph that looks similar to this below image.
Click on this link to view the image
I have searched across and have not found a solution for this using Cytoscape.
Yes, you can create bidirectional edges in Cytoscape.js. First, the curve-styles of your edges should be different than 'haystack' (below I set it as 'straight'), because 'haystack' doesn't support edge endpoint arrows. Second, you need to specify source and target endpoint arrow shapes. Possible values for arrow shapes are listed here (I used 'triangle-backcurve' below). If you want one directional edge, you can set the arrow shape only for source or target.
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
style: [{
selector: 'node',
css: {
'content': 'data(id)',
'text-valign': 'center',
'text-halign': 'center'
}
},
{
selector: 'edge',
css: {
'curve-style': 'straight',
}
}
],
elements: {
nodes: [{
data: {
id: 'n0'
}
},
{
data: {
id: 'n1'
}
},
{
data: {
id: 'n2'
}
},
{
data: {
id: 'n3'
}
}
],
edges: [{
data: {
id: 'n0n1',
source: 'n0',
target: 'n1'
}
},
{
data: {
id: 'n1n2',
source: 'n1',
target: 'n2'
}
},
{
data: {
id: 'n2n3',
source: 'n2',
target: 'n3'
}
}
]
}
});
cy.getElementById('n0n1').style({'source-arrow-shape': 'triangle-backcurve', 'target-arrow-shape': 'triangle-backcurve'});
cy.getElementById('n1n2').style({'target-arrow-shape': 'triangle-backcurve'});
cy.getElementById('n2n3').style({'source-arrow-shape': 'triangle-backcurve'});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 95%;
width: 95%;
left: 0;
top: 0;
position: absolute;
}
<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://unpkg.com/cytoscape#3.10.0/dist/cytoscape.min.js">
</script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
Related
I am using Cytoscape.js, to draw a Graph.
The problem is I want to adjust the zooming scale that the zoom event receives which the mouse wheel triggers.
Now when I scroll forward or backward the zoom increases or decreases more than expected... resulting in a bad user experience...
I couldn't find in the docs how to achieve or set this scale values...
I know that the wheel sensitivity is configurable but is not recommended to set.
Is there any way to establish how to scale in each wheel scroll?
The property you're looking for is wheelSensitivity. Adjust his value to change the zooming scale. Be careful with it because it can sometimes affect the render.
I put it at 0.4 in the example below:
<!DOCTYPE>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<style>
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
</style>
<script>
window.addEventListener('DOMContentLoaded', function(){
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
wheelSensitivity: 0.4,
style: [
{
selector: 'node',
style: {
'background-color': '#11479e'
}
},
],
elements: {
nodes: [
{ data: { id: 'n0' } },
{ data: { id: 'n1' } },
{ data: { id: 'n2' } },
],
edges: [
{ data: { source: 'n0', target: 'n1' } },
{ data: { source: 'n1', target: 'n2' } },
{ data: { source: 'n0', target: 'n2' } }
]
}
});
});
</script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
You can use the cy.minZoom() and cy.maxZoom() to set the values. The zoom levels shall be maintained between this range on mouse and touch zoom. My example below is to set zoom on click event
cy.on("click","node",function(event) {
cy.minZoom(0.5)
cy.maxZoom(2.5)
I have it set up in this codepen:I have two questions related to this solution using Tippy v4. related stackoverflow question
JS:
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
style: [{
selector: "node",
style: {
content: "data(id)"
}
},
{
selector: "edge",
style: {
"curve-style": "bezier",
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "a"
}
}, {
data: {
id: "b"
}
}],
edges: [{
data: {
id: "ab",
source: "a",
target: "b"
}
}]
},
layout: {
name: "grid"
}
}));
function makePopper(ele) {
let ref = ele.popperRef();
tippy(ref, {
// popperInstance will be available onCreate
lazy: false,
onCreate(instance) {
instance.popperInstance.reference = {
clientWidth: 10,
clientHeight: 10,
getBoundingClientRect() {
return {
w: 20, h:20
};
},
};
},
});
}
cy.ready(function() {
cy.elements().forEach(function(ele) {
makePopper(ele);
});
});
cy.elements().unbind('mouseover');
cy.elements().bind('mouseover', (event) => event.target.tippy.show());
cy.elements().unbind('mouseout');
cy.elements().bind('mouseout', (event) => event.target.tippy.hide());
});
HTML:
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/popper.js#1.14.7/dist/umd/popper.js">
</script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-popper#1.0.5/cytoscape-popper.min.js"></script>
<script src="https://unpkg.com/tippy.js#5/dist/tippy-bundle.iife.js">
</script>
<link rel="stylesheet"
href="https://unpkg.com/tippy.js#5/dist/backdrop.css">
</head>
<body>
<div id="cy"></div>
</body>
CSS:
body {
font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
font-size: 14px
}
#cy {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 1;
}
h1 {
opacity: 0.5;
font-size: 1em;
font-weight: bold;
}
1) Is it possible to make the Tippy follow the node as it is dragged? I have tried adding the property like this in cy.ready(), tippy.setDefaultProps({followCursor: 'true'}); But I get an error that the tippy.setDefaultProps() is not a function. I have set this Tippy v4 question up in this codepen: setDefaultProps codePen
tippy.setDefaultProps({followCursor: 'true'});
2) I cannot get the tippy example to work with Tippy v5. I get an error, tippy was passed as a plain object which is no longer supported. I have tried passing a ref object, but I get the same error. I have it v5 set up in this codepen:
Tippy v5 error The code shown above is the Tippy v5 code, but the Tippy v4 code is very similar.
I am looking for an example of showing Tooltips when hovering over nodes in Cytoscape graph.
I have seen several examples with popperjs and with qtip , non of them was working (for me at least)
cytoscape-qtip seems to be deprecated
example here (Tippy.js)
https://github.com/cytoscape/cytoscape.js-popper
seems not to work
You can use the code from here just fine, I made some adjustments myself, so that the tooltips appear on hover:
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
style: [{
selector: "node",
style: {
content: "data(id)"
}
},
{
selector: "edge",
style: {
"curve-style": "bezier",
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "a"
}
}, {
data: {
id: "b"
}
}],
edges: [{
data: {
id: "ab",
source: "a",
target: "b"
}
}]
},
layout: {
name: "grid"
}
}));
function makePopper(ele) {
let ref = ele.popperRef(); // used only for positioning
ele.tippy = tippy(ref, {
// tippy options:
content: () => {
let content = document.createElement("div");
content.innerHTML = ele.id();
return content;
},
trigger: "manual" // probably want manual mode
});
}
cy.ready(function() {
cy.elements().forEach(function(ele) {
makePopper(ele);
});
});
cy.elements().unbind("mouseover");
cy.elements().bind("mouseover", event => event.target.tippy.show());
cy.elements().unbind("mouseout");
cy.elements().bind("mouseout", event => event.target.tippy.hide());
});
body {
font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
font-size: 14px
}
#cy {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 1;
}
h1 {
opacity: 0.5;
font-size: 1em;
font-weight: bold;
}
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/popper.js#1.14.7/dist/umd/popper.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-popper#1.0.4/cytoscape-popper.min.js"></script>
<script src="https://unpkg.com/tippy.js#4.0.1/umd/index.all.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/tippy.js#4.0.1/index.css" />
</head>
<body>
<div id="cy"></div>
</body>
I want to change the color of the edge which connected a node(nodeA->nodeB and nodeB->nodeC) to red color, when clicking nodeC as in sample.png, by cytoscape.js. Please help me.
cy.on("tap", "node", (evt) => {evt.cyTarget.connectedEdges().animate({
style: {lineColor: "red"}
})
})`
When I use this code, it changed the colors of all edges that connected to the clicked node.
Cytoscape.js provides some neat functions to filter nodes:
incomers() gets edges (and their sources) coming into the nodes in the collection
predecessors() recursively gets edges (and their sources) coming into the nodes in the collection (i.e. the incomers, the incomers' incomers, ...)
edges() gets edges in the graph matching the specified selector
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
content: "data(id)",
"text-valign": "center",
"text-halign": "center",
height: "60px",
width: "100px",
shape: "rectangle",
"background-color": "data(faveColor)"
}
},
{
selector: "edge",
css: {
"curve-style": "bezier",
"control-point-step-size": 40,
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "Top",
faveColor: "#2763c4"
}
},
{
data: {
id: "yes",
faveColor: "#37a32d"
}
},
{
data: {
id: "no",
faveColor: "#2763c4"
}
},
{
data: {
id: "Third",
faveColor: "#2763c4"
}
},
{
data: {
id: "Fourth",
faveColor: "#56a9f7"
}
}
],
edges: [{
data: {
source: "Top",
target: "yes"
}
},
{
data: {
source: "Top",
target: "no"
}
},
{
data: {
source: "no",
target: "Third"
}
},
{
data: {
source: "Third",
target: "Fourth"
}
}
]
},
layout: {
name: "dagre"
}
}));
cy.unbind('click');
cy.bind('click', 'node', function(node) {
console.log(node.target.predecessors().edges());
node.target.predecessors().edges().animate({
style: {
lineColor: "red"
}
});
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
left: 0;
top: 0;
float: left;
position: absolute;
}
<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://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js">
</script>
<!-- cyposcape dagre -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.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>
I an novice in js and cytoscape. I want to display cytoscape graph in server with an save button for saving it as png. I checked cytoscape documentation but did not understand how to put an image tag on cytoscape graph. Please help me. I checked earlier posts in stackoverflow and github also.
My js script is here :
$(function(){ //
var cy = cytoscape({
container: document.getElementById('cy'),
style: cytoscape.stylesheet()
.selector('node')
.css({
'label': 'data(label)',
'width': '60px',
'height': '60px',
'color': 'blue',
'background-color': 'blue',
})
.selector('edge')
.css({
'text-background-color': 'blue',
'text-background-opacity': 0.4,
'width': '6px',
'line-color': '#3C1515'})
,elements:{
nodes:[
{ data: { id:"node1",label:" node1 " } },
{ data: { id:"node2",label:" node2 " } },
{ data: { id:"node3",label:" node3 " } }
],
edges:[
{"data": {"id": "12","source": "node1","target": "node2"}},
{"data": {"id": "13","source": "node1","target": "node3"}}
]
},
layout: { name: "circle",directed: true,padding: 10 }
}); // var cy cytoscope ends
var png64 = cy.png();
// put the png data in an img tag
$('#png-eg').attr('src', png64);
});
The html code is :
<html>
<style>
#cy {width: 80%;height: 80%;position: absolute;top: 20px;left: 20px;}
</style>
<script src="jquery.js"></script>
<script src="cytoscape.js"></script>
<script src="javascript-code.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
Your code simply doesn't contain the required img tag, so just add it to your html or add it with js/jquery:
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
style: [
{
selector: 'node',
css: {
'content': 'data(id)',
'text-valign': 'center',
'text-halign': 'center'
}
},
{
selector: '$node > node',
css: {
'padding-top': '10px',
'padding-left': '10px',
'padding-bottom': '10px',
'padding-right': '10px',
'text-valign': 'top',
'text-halign': 'center',
'background-color': '#bbb'
}
},
{
selector: 'edge',
css: {
'target-arrow-shape': 'triangle'
}
},
{
selector: ':selected',
css: {
'background-color': 'black',
'line-color': 'black',
'target-arrow-color': 'black',
'source-arrow-color': 'black'
}
}
],
elements: {
nodes: [
{ data: { id: 'a', parent: 'b' }, position: { x: 215, y: 85 } },
{ data: { id: 'b' } },
{ data: { id: 'c', parent: 'b' }, position: { x: 300, y: 85 } },
{ data: { id: 'd' }, position: { x: 215, y: 175 } },
{ data: { id: 'e' } },
{ data: { id: 'f', parent: 'e' }, position: { x: 300, y: 175 } }
],
edges: [
{ data: { id: 'ad', source: 'a', target: 'd' } },
{ data: { id: 'eb', source: 'e', target: 'b' } }
]
},
layout: {
name: 'preset',
padding: 5
}
});
cy.ready(function () {
//if you want to create the img tag afterwards:
//$('#right').prepend("<img id='png-eg'>");
var png64 = cy.png();
// put the png data in an img tag
$('#png-eg').attr('src', png64);
});
$("#clickMe").click(function () {
var png64 = cy.png();
// put the png data in an img tag
$('#png-eg').attr('src', png64);
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
#png-eg {
border: 1px solid #ddd;
min-width: 3em;
min-height: 3em;
width: 25%;
float: right;
}
<!DOCTYPE html>
<!-- This code is for demonstration purposes only. You should not hotlink to Github, Rawgit, or files from the Cytoscape.js documentation in your production apps. -->
<html>
<head>
<link href="style.css" rel="stylesheet" />
<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">
<title>Compound nodes</title>
<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>
</head>
<body>
<div id="wrapper">
<div id="cy"></div>
<div id="right"><button id="clickMe" style="float: right;">Click me</button><img id="png-eg"></div>
</div>
</body>
</html>