Disable the overlap of nodes - javascript

I have created visualisation using vis-network, the problem is that the nodes are overlapping one on top of the other.
I have tried changing different values of nodeSpacing till 1000, that didn't help
Also i have tried setting barnesHut.avoidOverlap to 1 and that didn't help either,
any suggestions to fix this will be highly appreciated.
Updated options object
var options = {
interaction: {
hover: true
},
manipulation: {
enabled: true,
},
layout: {
hierarchical: {
direction: "LR",
shakeTowards: "leaves",
nodeSpacing: 1000,
treeSpacing: 300,
},
},
physics: {
stabilization: {
enabled: true, // <------ Disables animation.
iterations: 4000
},
barnesHut: {
avoidOverlap: 1
}
}
};

As mentioned in the documentation here for the layout.hierarchical.nodeSpacing option:
This is only for the initial layout. If you enable physics, the node distance there will be the effective node distance.
Therefore nodeSpacing isn't the final distance when physics is enabled. Two possible options are described below with examples.
nodeSpacing with Physics Disabled
The nodeSpacing option could be used with physics disabled. With physics disabled edges will likely overlap nodes when there are a large number of nodes. An example of this can be seen at https://jsfiddle.net/pbx8m9sk/.
nodeDistance with Hierarchical Repulsion Solver
As mentioned in the solver section of the documentation here the hierarchical repulsion solver is used by default when using a hierarchical layout. When the hierarchicalRepulsion solver is used the nodeDistance option can be used to control the distance between the nodes.
For example:
var options = {
physics: {
hierarchicalRepulsion: {
nodeDistance: 300,
}
}
};
Snippet using hierarchical repulsion solver with node distance set is below. You would likely want to adjust the nodeDistance and could adjust other hierarchicalRepulsion options, depending on the data.
// Setup initial nodes / edges
const nodes = [
{id: 1, label: '1'},
{id: 2, label: '2'},
{id: 3, label: '3'},
{id: 4, label: '4'},
{id: 5, label: '5'},
{id: 6, label: '6'},
{id: 7, label: '7'},
{id: 8, label: '8'},
{id: 9, label: '9'},
{id: 10, label: '10'},
{id: 11, label: '11'},
];
const edges = [
{from: 1, to: 2},
{from: 2, to: 3},
{from: 2, to: 4},
{from: 2, to: 5},
{from: 2, to: 6},
{from: 2, to: 7},
{from: 2, to: 8},
{from: 2, to: 9},
{from: 2, to: 10},
{from: 2, to: 11},
];
// Add a number nodes / edges
const nodesToAdd = 200;
for (let i = 12; i < 12 + nodesToAdd; i++){
nodes.push({id: i, label: `${i}`});
edges.push({from: 11, to: i});
}
var data = {
nodes: nodes,
edges: edges,
};
// create a network
var container = document.getElementById("mynetwork");
var options = {
interaction: {
hover: true
},
manipulation: {
enabled: true
},
nodes: {
shape: 'dot',
},
layout: {
hierarchical: { },
},
physics: {
hierarchicalRepulsion: {
nodeDistance: 300,
}
},
};
var network = new vis.Network(container, data, options);
#mynetwork {
width: 100%;
height: 170px;
border: 1px solid lightgray;
}
<script src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"></script>
<div id="mynetwork"></div>

Related

Can I have a grid as background on a Vis.js Network

I'm implementing a network chart using Vis.js, and I'd like to have a grid as background
Do you have any idea how can I achieve that and if I can achieve that?
Example using beforeDrawing (per this example):
// create an array with nodes
var nodes = new vis.DataSet([
{ id: 1, value: 2, label: "Algie" },
{ id: 2, value: 31, label: "Alston" },
{ id: 3, value: 12, label: "Barney" },
{ id: 4, value: 16, label: "Coley" },
{ id: 5, value: 17, label: "Grant" },
{ id: 6, value: 15, label: "Langdon" },
{ id: 7, value: 6, label: "Lee" },
{ id: 8, value: 5, label: "Merlin" },
{ id: 9, value: 30, label: "Mick" },
{ id: 10, value: 18, label: "Tod" },
]);
// create an array with edges
var edges = new vis.DataSet([
{ from: 2, to: 8, value: 3, title: "3 emails per week" },
{ from: 2, to: 9, value: 5, title: "5 emails per week" },
{ from: 2, to: 10, value: 1, title: "1 emails per week" },
{ from: 4, to: 6, value: 8, title: "8 emails per week" },
{ from: 5, to: 7, value: 2, title: "2 emails per week" },
{ from: 4, to: 5, value: 1, title: "1 emails per week" },
{ from: 9, to: 10, value: 2, title: "2 emails per week" },
{ from: 2, to: 3, value: 6, title: "6 emails per week" },
{ from: 3, to: 9, value: 4, title: "4 emails per week" },
{ from: 5, to: 3, value: 1, title: "1 emails per week" },
{ from: 2, to: 7, value: 4, title: "4 emails per week" },
]);
// create a network
var container = document.getElementById("mynetwork");
var data = {
nodes: nodes,
edges: edges,
};
var options = {
nodes: {
shape: "dot",
},
};
var network = new vis.Network(container, data, options);
network.on("beforeDrawing", function(ctx) {
var width = ctx.canvas.clientWidth;
var height = ctx.canvas.clientHeight;
var spacing = 40;
var gridExtentFactor = 4;
ctx.strokeStyle = "lightgrey";
// draw grid
ctx.beginPath();
for (var x = -width * gridExtentFactor; x <= width * gridExtentFactor; x += spacing) {
ctx.moveTo(x, height * gridExtentFactor);
ctx.lineTo(x, -height * gridExtentFactor);
}
for (var y = -height * gridExtentFactor; y <= height * gridExtentFactor; y += spacing) {
ctx.moveTo(width * gridExtentFactor, y);
ctx.lineTo(-width * gridExtentFactor, y);
}
ctx.stroke();
});
#mynetwork {
width: 600px;
height: 200px;
border: 1px solid lightgray;
background-color: none;
}
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
<div id="mynetwork"></div>
vis-network uses a html5 canvas to draw the chart. You could draw the grid yourself using the beforeDrawing event. To support interactivity like zooming and panning you would also need to listen to the dragStart, dragging and dragEnd events as well as zoom. With these events it should be possible to implement a fully interactive background.
Have a look at the renderEvents example and the interactionEvents example.

JavaScript, HTML, CSS to Class diagram

I been searching around for a tool that can help me generate class diagram for my web development project.
I have one plugin for eclipse but it only works for the JavaScript and does not link the HTML and CSS - http://jsuml.org/.
Found another that does sort of what I want but it requires me to use npm, however, since I didnt use this in my project from start its quite difficult for me to change the structure now - https://www.npmjs.org/package/wavi
I am using visual code to write my code but am happy to move my code to another editor if it gets the job done (as long as its windows) :)
The result I am looking for is something like below:
Please let me know if I have posted this in the wrong section and I be happy to move it.
I found some plugins for visual code but there all seem to be for sequence diagram and none for class diagram.
Here is an example using vis js:
// create an array with nodes
var nodes = new vis.DataSet([{
id: 1,
label: 'Node 1'
},
{
id: 2,
label: 'Node 2'
},
{
id: 3,
label: 'Node 3'
},
{
id: 4,
label: 'Node 4'
},
{
id: 5,
label: 'Node 5'
},
{
id: 6,
label: 'Node 6'
},
{
id: 7,
label: 'Node 7'
},
{
id: 8,
label: 'Node 8'
}
]);
// create an array with edges
var edges = new vis.DataSet([{
from: 1,
to: 8,
arrows: 'to',
dashes: true
},
{
from: 1,
to: 3,
arrows: 'to'
},
{
from: 1,
to: 2,
arrows: 'to, from'
},
{
from: 2,
to: 4,
arrows: 'to, middle'
},
{
from: 2,
to: 5,
arrows: 'to, middle, from'
},
{
from: 5,
to: 6,
arrows: {
to: {
scaleFactor: 2
}
}
},
{
from: 6,
to: 7,
arrows: {
middle: {
scaleFactor: 0.5
},
from: true
}
}
]);
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {};
var network = new vis.Network(container, data, options);
#myNetwork {
width: 400px;
height: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
<div id='mynetwork'></div>
More example can be found here

Visjs network place node fixed at bottom right

I would like to create a node in the network plugin of the visjs framework, so that it stays fixed at the bottom.
Getting it staying fixed is no problem, however the rest of the nodes seem to have somekind of algorithm for the x and y coordinates.
Doing a { x: 0, y: 0 } will not work it seems because the x and y are coordinates in relation to other nodes.
I think (if I got you right), you should:
set physics to false.
give fixed position to true for all nodes,
set the node positions as you wish.
after drawing the network (in the next tick) remove the fixed position from all other nodes.
See the snippet below. (the fixed position stays on node no 5).
// create an array with nodes
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1', fixed: true, group: 1, x:0, y:0},
{id: 2, label: 'Node 2', fixed: true, group: 2, x:10, y:110},
{id: 3, label: 'Node 3', fixed: true, group: 1, x:120, y:20},
{id: 4, label: 'Node 4', fixed: true, group: 2, x:-110, y:-110},
{id: 5, label: 'Node 5', fixed: true, group: 2, x:220, y:220}
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 2, to: 4},
{from: 3, to: 4},
{from: 2, to: 5}
]);
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
physics: false
};
var network = new vis.Network(container, data, options);
setTimeout(function(){
nodes.forEach(node => {
if(node.id !== 5){
nodes.update({id: node.id, fixed: false});
}
})
})
#mynetwork {
width: 600px;
height: 400px;
border: 1px solid lightgray;
}
p {
max-width: 600px;
}
<!doctype html>
<html>
<head>
<title>Network | Basic usage</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.20.0/vis.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.20.0/vis.min.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="mynetwork"></div>
</body>
</html>

vis.js large nodes overlapping in hierarchical mode

Is it possible to have nodes in vis.js in hierarchical layout without overlaping on X axis?
I tried to add options:
var options = {
layout: {
hierarchical: {
direction: "UD",
sortMethod: "directed"
},
physics: {
solver: "barnesHut"
,barnesHut: {
avoidOverlap: 1
}
}
}
};
You can increase layout.hierarchical.nodeSpacing for the initial layout.
// create an array with nodes
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1 with lage text'},
{id: 2, label: 'Node 2 with lage text'},
{id: 3, label: 'Node 3 with lage text'},
{id: 4, label: 'Node 4 with lage text'},
{id: 5, label: 'Node 5 with lage text'}
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
layout: {
hierarchical: {
direction: "UD",
sortMethod: "directed",
nodeSpacing: 200 // <-- !!!!!!!
}
},
physics: false
};
var network = new vis.Network(container, data, options);
#mynetwork {
width: 100%;
height: 100%;
border: 1px solid lightgray;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.17.0/vis.min.js" type="text/javascript"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.17.0/vis.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="mynetwork"></div>
</body>
</html>
Another solution might be
myVisOptions = {
layout: {
hierarchical: {
direction: "UD",
sortMethod: "directed",
shakeTowards: 'roots'
}
},
physics: {
// https://visjs.github.io/vis-network/docs/network/physics.html
enabled: true,
hierarchicalRepulsion: {
avoidOverlap: 0.99
},
stabilization: {
iterations: 2000,
updateInterval: 100
},
solver: 'hierarchicalRepulsion'
},
nodes: {
margin: 8,
shape: 'box',
font: {size: 20},
color: {
background: 'white',
border: '#ffc468',
hover: '#ffc468',
highlight: '#ffc468'//, '#bd6500'
},
}
};

How to show label when mouse over bar

I made a Bar chart by chartist.js.
Now I want to add some listening event on the bars.
How can I do to let label show up when mouse over the bar?
You have 2 options -
Option 1
There is a tooltip plugin that you could use. You can find it here - https://github.com/Globegitter/chartist-plugin-tooltip
Once you add the CSS and JS files, you should be able to call the plugin like this - Chartist.plugins.tooltip()
Here is an example from their Plugins page -
var chart = new Chartist.Line('.ct-chart', {
labels: [1, 2, 3],
series: [
[
{meta: 'description', value: 1 },
{meta: 'description', value: 5},
{meta: 'description', value: 3}
],
[
{meta: 'other description', value: 2},
{meta: 'other description', value: 4},
{meta: 'other description', value: 2}
]
]
}, {
low: 0,
high: 8,
fullWidth: true,
plugins: [
Chartist.plugins.tooltip()
]
});
This will be the easier and the better option.
Option 2
If you want to do something by yourself, you can bind mouseover and mouseout events on draw event's callback -
var data = {
labels: ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8', 'W9', 'W10'],
series: [
[1, 2, 4, 8, 6, -2, -1, -4, -6, -2]
]
};
var options = {
high: 10,
low: -10,
axisX: {
labelInterpolationFnc: function(value, index) {
return index % 2 === 0 ? value : null;
}
}
};
var chart = new Chartist.Bar('.ct-chart', data, options);
// Based on ty's comment
chart.on('created', function(bar) {
$('.ct-bar').on('mouseover', function() {
$('#tooltip').html('<b>Selected Value: </b>' + $(this).attr('ct:value'));
});
$('.ct-bar').on('mouseout', function() {
$('#tooltip').html('<b>Selected Value:</b>');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/chartist.js/0.9.5/chartist.min.js"></script>
<link href="https://cdn.jsdelivr.net/chartist.js/0.9.5/chartist.min.css" rel="stylesheet" />
<div id="tooltip"><b>Selected Value:</b>
</div>
<div class="ct-chart"></div>
UPDATE: Updated the code as per ty's comment

Categories