I would like to simply show/hide the labels of the edges of my vis.js-network - is this possible?
I have tried to update the edges in the vis.js-data structure:
Delete the label property - doesn't work
Set the label to undefined - doesn't work
Set the label to '' - doesn't work
Set the label to ' ' - works
I would prefer a network-wise toggle of some kind, but I haven't found one.
Is there a better way of doing this?
An alternative to updating the label property on each edge is to change the font color to be transparent for all edges. The setOptions() method can be used to update the options and will apply all edges in the network. The options edges.font.color and edges.font.strokeColor should both be updated, then returned to their original values to display the edges.
Example below and also at https://jsfiddle.net/rk9s87ud/.
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" },
]);
var edges = new vis.DataSet([
{ from: 1, to: 2, label: 'Edge 1' },
{ from: 2, to: 3, label: 'Edge 2' },
{ from: 3, to: 4, label: 'Edge 3' },
{ from: 4, to: 5, label: 'Edge 4' },
]);
var container = document.getElementById("mynetwork");
var data = {
nodes: nodes,
edges: edges,
};
var options = {
nodes: {
// Set any other options, for example node color to gold
color: 'gold'
},
edges: {
font: {
// Set to the default colors as per the documentation
color: '#343434',
strokeColor: '#ffffff'
}
}
}
var hiddenEdgeTextOptions = {
edges: {
font: {
// Set the colors to transparent
color: 'transparent',
strokeColor: 'transparent'
}
}
};
var network = new vis.Network(container, data, options);
var displayLabels = true;
document.getElementById('toggleLabels').onclick = function() {
if(displayLabels){
// Apply options for hidden edge text
// This will override the existing options for text color
// This does not clear other options (e.g. node.color)
network.setOptions(hiddenEdgeTextOptions);
displayLabels = false;
} else {
// Apply standard options
network.setOptions(options);
displayLabels = true;
}
}
#mynetwork {
width: 600px;
height: 160px;
border: 1px solid lightgray;
}
<script src="https://visjs.github.io/vis-network/standalone/umd/vis-network.min.js"></script>
<button id="toggleLabels">Toggle labels</button>
<div id="mynetwork"></div>
Related
After reading the ECharts documentation and looking at examples, I haven't found anything that would allow coloring or highlight tree branch when I clicked a specific node and draw a path up to their children leaves.
Basically, I'm trying to do something like this ECharts tree example:
It is theoretically possible, but I did not have time to practice. In general my thought in the next steps:
Subscribe to listen click events for symbol, see events.
Get current (clicked) series and get rid for another series for exclude parents, it's can be done with instance.getModel().getSeries() or instance.getModel().eachSeries(...)
After it we have the only children nodes. Now you can change (with instance.setOption({...})) children leaves' lineStyle and paint it black.
If you do not succeed, I'll try later.
Update
I made what you wanted but code is dirty and not easy for learn, sorry I was hurry. Let me know if you have any question.
var container = document.getElementById('main');
var chart = echarts.init(container);
var data = {
name: "node 1",
children: [{
name: "node 1.1",
children: [{
name: "node 1.1.1",
children: [{
name: "node 1.1.1.1",
value: 721
}]
},
{
name: "node 1.1.2",
children: [{
name: "node 1.1.2.1",
value: 727,
children: [{
name: "node 1.1.2.1.1",
children: [{
name: "node 1.1.2.1.1.1",
value: 727
}]
}, {
name: "node 1.1.2.1.2",
children: [{
name: "node 1.1.2.1.2.1",
value: 727
}]
}]
}]
},
{
name: "node 1.1.3",
children: [{
name: "node 1.1.3.1",
value: 725
}]
}]
}]
};
var option = {
tooltip: {
trigger: 'item',
triggerOn: 'mousemove'
},
series: [{
type: 'tree',
id: 0,
name: 'tree1',
data: [data],
top: '10%',
left: '8%',
bottom: '22%',
right: '20%',
symbolSize: 7,
edgeShape: 'curve',
edgeForkPosition: '10%',
initialTreeDepth: 5,
lineStyle: {
width: 3,
curveness: 0.3
},
label: {
backgroundColor: '#fff',
position: 'left',
verticalAlign: 'middle',
align: 'right',
borderColor: 'red',
borderWidth: 1,
borderRadius: 10,
padding: 10
},
leaves: {
label: {
position: 'right',
verticalAlign: 'middle',
align: 'left'
}
},
expandAndCollapse: true,
animation: false,
}]
};
chart.setOption(option);
var hoverStyle = { lineStyle: { color: 'black' }};
// Traverse each node in tree
function traverse(node, callback){
if(node.children){
callback(node);
node.children.forEach(subNode => traverse(subNode, callback))
} else {
callback(node)
}
}
// Traverse from target node
function traverseFrom(opts){
var defaults = { tree: data, nodeName: null, callback: null, skipStartNode: false };
Object.assign(defaults, opts);
var targetNode = null;
// Find node for start paint
traverse(defaults.tree, node => {
if(node.name === defaults.nodeName){
targetNode = node;
}
});
// Find all children of found node
traverse(targetNode, node => {
if(defaults.skipStartNode && node.name === defaults.nodeName){
// Skip first because it is start branch
} else {
defaults.callback(node)
}
});
}
// Build new config with painted nodes
function buildSeriesConfig(nodes, style){
var seriesConfig = echarts.util.clone(data);
var nodes = [...nodes].flat();
traverse(seriesConfig, node => {
if(nodes.includes(node.name)){
Object.assign(node, style);
}
});
return seriesConfig
};
// General paint function
function paintBranch(chartInstance, nodeName){
var nodesForPaint = [];
var newSeries = null;
var mainOption = null;
traverseFrom({
nodeName: nodeName,
callback: node => nodesForPaint.push(node.name),
skipStartNode: true
});
if(nodesForPaint){
newSeries = buildSeriesConfig(nodesForPaint, hoverStyle)
} else {
throw 'Nodes for paint is not exists'
}
if(newSeries){
chartInstance.setOption({
series: [{ type: 'tree', id: '0', data: [newSeries] }]
}, false);
} else {
throw 'New series config is not builded'
}
};
function isNodeSelected(tree, nodeName){
var status = false;
traverseFrom({
tree: tree,
nodeName: nodeName,
callback: node => {
if(node.hasOwnProperty('lineStyle')) status = true;
},
skipStartNode: true
})
return status
}
function cleanTree(chartInstance){
var clonedData = echarts.util.clone(data);
chartInstance.setOption({
series: [{ type: 'tree', id: '0', data: [clonedData] }]
}, false);
};
chart.on('click', (e) => {
var chartTree = chart.getOption().series[0].data[0];
var nodeSelected = isNodeSelected(chartTree, e.name);
if(nodeSelected){
cleanTree(chart)
} else {
paintBranch(chart, e.name)
}
});
<script src="https://cdn.jsdelivr.net/npm/echarts#4.7.0/dist/echarts.js"></script>
<div id="main" style="width: 800px;height:600px; margin: 100px"></div>
Can we show a different graph say pie chart in the tooltip hover in the bar chart using nvd3?
Here is one sample which is doing the job. The logic behind this approach is the following:
Disable the default tooltip
Prepare helper chart(donut chart in the example) which is going to be used as a tooltip
In the callback of the main chart (bar chart) register event listeners on the bar elements
mousemove - to show and position the custom donut chart tooltip
mouseleave - to hide the tooltip
var donutContainer = document.getElementById('donut-chart');
var chartDonut;
var chartBar;
nv.addGraph(function() {
chartBar = nv.models.discreteBarChart()
.x(d => d.label)
.y(d => d.value)
.margin({left: 80})
.showValues(true)
.duration(250);
// Disable the default tooltip
chartBar.tooltip.enabled(false);
d3.select('#main-chart svg')
.datum(historicalBarChart)
.call(chartBar);
nv.utils.windowResize(chartBar.update);
return chartBar;
}, () => {
// After the chart is loaded register some listeners
// to determine when to show/hide the custom tooltip chart
var bars = d3.selectAll('.nv-bar');
bars.on('mousemove', function(bar) {
// When the mouse is moved across bar
// show the tooltip chart and update tooltip position
d3.select('#donut-chart svg')
.datum(bar.details)
.call(chartDonut);
nv.utils.windowResize(chartDonut.update);
var e = window.event;
donutContainer.style.display = 'block';
donutContainer.style.left = e.clientX + "px";
donutContainer.style.top = e.clientY - 50 + "px";
});
// When the mouse leaves a bar then hide the tooltip
bars.on('mouseleave', e => donutContainer.style.display = 'none');
});
// Prepare the donut chart for the tooltip
nv.addGraph(function() {
// Note here that duration(0) is used. This is done
// because when you move the cursor between bars with different
// child group count( e.g. OS and Shoes) error is thrown
chartDonut = nv.models.pieChart()
.x(d => d.name)
.y(d => d.value)
.width(150)
.height(150)
.donut(true)
.duration(0)
.showLegend(false);
chartDonut.tooltip.enabled(false);
return chartDonut;
});
// Sample data
const historicalBarChart = [{
key: 'Cumulative Return',
values: [{
label: 'Cars',
value: 1500000,
details: [{
name: 'Audi',
value: 500000
}, {
name: 'Mercedes',
value: 700000
}, {
name: 'Ford',
value: 300000
}]
}, {
label: 'Mobile',
value: 1000000,
details: [{
name: 'iPhone',
value: 500000
}, {
name: 'Samsung',
value: 410000
}, {
name: 'Lenovo',
value: 90000
}]
}, {
label: 'OS',
value: 1500000,
details: [{
name: 'OSX',
value: 500000
}, {
name: 'Windows',
value: 500000
}, {
name: 'Linux',
value: 500000
}]
}, {
label: 'Shoes',
value: 1400000,
details: [{
name: 'Addidas',
value: 500000
}, {
name: 'Nike',
value: 500000
}, {
name: 'Puma',
value: 100000
}, {
name: 'Something',
value: 300000
}]
}]
}];
text {
font: 12px sans-serif;
}
svg {
display: block;
}
html,
body,
#main-chart,
svg {
height: 100%;
width: 400px;
}
#donut-chart {
position: absolute;
height: 150px;
width: 150px;
background-color: white;
z-index: 1;
pointer-events: none;
display: none;
border: 1px solid black;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.js"></script>
<div id="main-chart"> <svg></svg></div>
<div id="donut-chart"><svg></svg></div>
I'm using c3 js for generating categories bar chart
Here is code
var obj = {
size: {
height: 200,
},
bindto: '#grBarChart',
data: {
columns: data.columns,
type: "bar"
},
color: {
pattern: ['#c90000', '#008cba', '#FAAC3D','#427322', '#9ead9b', '#ffa500']
},
axis: {
x: {
type: 'category',
categories: data.categories,
label: {
text: 'Scanned Groups',
position: 'outer-center'
}
},
y: {
label: {
text: 'Count (Rules)',
position: 'outer-middle'
}
}
},
bar: {
width: {
ratio: 0.5,
}
},
grid: {
y: {
show: true
}
}
};
var chart = c3.generate(obj);
This code is generating the following graph
Now my problem is I'm not able to add click event on X Axis Category Names ( Logging 11, Data Protection 13 ...)
I referred C3 Documentation but not able to solve my problem.
Please give me your thought?
I am using cytoscape.js for converting a raw txt data to cytoscape.js graph.
for that, first I make the graph with :
var cy = cytoscape({...})
without any elements.Then after reading nodes and edges from txt file, I add them with this for nodes :
cy.add({
data: {id: keys[i]}
}
);
and this for edges:
cy.add({
data: {
id: 'edge' + i,
source: edges[i].source,
target: edges[i].target,
label: edges[i].weight
}
});
Then i want to apply 'width': 'mapData(weight, 0, 100, 1, 6)'. how can I do that?
I tried these:
1) using mapData() in edge selector when making cy variable.(it doesnt works for added edges and nodes)
2) using mapData() for each edge after making each of them:
cy.$('#edge' + i).style('width','mapData(weight, 0, 100, 1, 6)');
3) using mapData() after making all nodes and edges :
cy.elements('edge').style('line-color','mapData(weight,1,6,blue,green)');
none of them works!
Maybe like this:
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
style: [
{
selector: 'node',
style: {
'label': 'data(name)',
'width': 'mapData(weight, 0, 100, 1, 6)',
'height': 'mapData(weight, 0, 100, 1, 6)',
}
}
]
});
cy.add([
{ group: "nodes", data: { id: "n0", name: "node0", weight: "x"} },
{ group: "nodes", data: { id: "n1", name: "node1", weight: "y"} },
{ group: "edges", data: { id: "e0", source: "n0", target: "n1" } }
]);
cy.ready(function () { // Wait for nodes to be added
cy.layout( // Call layout
name: 'yourDecision'
).run();
});
I define the cytoscape instance on initialization and there I define the style of the nodes/edges/... .
Is there a way to change the node size for the selected node without changing the size for all nodes in the options ?
These are my node options:
nodes: {
borderWidth: 1,
borderWidthSelected: 2,
physics: true,
color: {
border: '#000000',
background: '#ffffff',
highlight: {
border: '#000000',
background: '#B9B9BF'
}
},
shadow: {
enabled: false,
color: '#C11818',
size: 10,
x: 5,
y: 5
},
shape: 'circularImage',
mass: 2,
size: 25
}
I want to enlarge the selected node so it is more visible than the others.
network.on("selectNode", function (params) {
var nodeId = params.nodes[0];
var node = nodes.get(nodeId);
nodeClick(nodeId, nodes, edges, network);
// var options= {
// nodes: {
// size: 40
// }
// };
// network.setOptions(options);
});
The commented part sets the size for all nodes rather than the one selected and the node object doesn't have any handle on the options either.
You can change the font-size of the selected node to increase its size:
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
var edges = new vis.DataSet([
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
interaction: { hover:true },
nodes: { font: { size: 14 }}
};
var network = new vis.Network(container, data, options);
network.on("selectNode", function (params) {
var selectedNodeId = params.nodes[0];
var node = network.body.nodes[selectedNodeId];
node.setOptions({
font: {
size: 20
}
});
});
network.on("deselectNode", function (params) {
var deselectedNodeId = params.previousSelection.nodes[0];
var node = network.body.nodes[deselectedNodeId];
node.setOptions({
font: {
size: options.nodes.font.size
}
});
});
#mynetwork {
width: 100%;
height: 100%;
border: 1px solid lightgray;
}
<!DOCTYPE html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/vis/4.16.1/vis.min.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="mynetwork"></div>
</body>
</html>
if you have multiselect enabled, you can loop over params.nodes
for (id in params.nodes){
var node = network.body.nodes[params.nodes[id]];
...
}
(deselect respectivly)