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/... .
Related
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>
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>
There are 3 nodes in the example,I use modifier key + mousedown then drag,I can select 2 nodes and drag them,the problem is after I release the mouse,I can not see which nodes I have selected.They are not highlight or with shadow or reversed color or with some sign to mark they are selected.
<style>
#cy{
width:600px;
height:800px
}
</style>
<script src="cytoscape.js"></script>
<div id="cy"></div>
<script>
var cy = cytoscape({
container: document.getElementById('cy'), // container to render in
elements: [ // list of graph elements to start with
{ // node a
data: { id: 'a' }
},
{ // node b
data: { id: 'b' }
},
{ // node c
data: { id: 'c' }
},
{ // edge ab
data: { id: 'ab', source: 'a', target: 'b' }
}
],
style: [ // the stylesheet for the graph
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'grid',
rows: 1
},
boxSelectionEnabled:true,
panningEnabled: true
});
</script>
You can store the selected node(s) in a variable or array and then add a mouseUp event, in which you highlight the nodes in said variable or array.
http://js.cytoscape.org/#events/user-input-device-events
Here you find the bind for cytoscape (always unbind events before binding them again):
http://js.cytoscape.org/#cy.on
cy.unbind('mouseup');
cy.bind('mouseup',/* 'node', */ function () {});
I am trying to add labels to my bar chart. See the JS fiddle and code below. How would I change my code to add labels?
http://jsfiddle.net/amwmedia/8kqvyhqv/
var myNewChart;
var data = [
{
value: 30,
label: "hello",
color: "#F7464A"
}, {
value: 50,
color: "#E2EAE9"
}, {
value: 100,
color: "#D4CCC5"
}, {
value: 40,
color: "#949FB1"
}, {
value: 100,
color: "#4D5360"
},
];
var options = {
animation: true,
animationEasing: 'easeInOutQuart',
animationSteps: 80,
multiTooltipTemplate: "<%= datasetLabel %> - <%= value %>"
};
var ctx = document.getElementById("myChart")
.getContext("2d");
myNewChart = new Chart(ctx).Doughnut(data, options);
I noticed your jsfiddle is using chart.js version 1. My answer uses version 2, as that is all I could find documentation for.
Looks like all you need to do is put labels in the data object:
var data = {
labels: [
"label1",
"label2",
"label3",
"label4",
"label5"
],
datasets: [
{
data: [
30,
50,
100,
40,
100
],
backgroundColor:[
'#F7464A',
'#E2EAE9',
'#D4CCC5',
'#949FB1',
'#4D5360'
]
}]
};
See fiddle. (this is using Chart.js 2.0)
I'm trying remove (or clean a canvas) from my div, but the event kill only removes the properties of the element but not the image. What I can do? This is my code:
var s = new sigma('container');
s.graph
.addNode({
id: 'n0',
label: 'Start',
x: 0,
y: 0.5,
size: 1,
color: '#f00'
})
.addNode({
id: 'n1',
label: 'End',
x: 1,
y: 0.5,
size: 1,
color: '#00f'
})
.addEdge({
id: 'e0',
source: 'n0',
target: 'n1'
});
s.settings({
edgeColor: 'default',
defaultEdgeColor: 'grey'
});
s.refresh();
$(function(){
$("#shape").click(function(){
//s.kill();
//s = new sigma('container');
s.graph
.addNode({
id: 'n3',
label: 'Start',
x: 0,
y: 0,
size: 1,
color: '#f00'
})
.addNode({
id: 'n4',
label: 'End',
x: 1,
y: 1,
size: 1,
color: '#00f'
})
.addEdge({
id: 'e1',
source: 'n3',
target: 'n4'
});
s.settings({
edgeColor: 'default',
defaultEdgeColor: 'grey'
});
s.refresh();
console.log("added!");
});
});
There's surely a better way to do this, but I have the same problem. I solved it by completely removing the DOM element containing the graph, and then recreating it:
HTML:
<div id="graph-container">
<div id="graph"></div>
</div>
JavaScript:
var sigma_graph = null;
function create_graph() {
sigma_graph = new sigma({ ... });
... populate graph ...
}
function refresh_graph() {
// to delete & refresh the graph
var g = document.querySelector('#graph');
var p = g.parentNode;
p.removeChild(g);
var c = document.createElement('div');
c.setAttribute('id', 'graph');
p.appendChild(c);
create_graph();
}
Note that I'm not using jQuery, otherwise it would have been something like:
$('#graph').remove();
$('#graph-container').html('<div id="graph"></div>');
While this method seems to work, I can't say if it's a good idea or not. (I'm using the canvas renderer, if that matters.)
You can re-use instances of sigma, you don't need to kill the instance completely. I had the same problem and this is how I solved it. Just have one sigma instance and clear it whenever you want a new graph.
s = new sigma({...});
//do stuff with the graph.
function clear_graph() {
//this gets rid of all the ndoes and edges
s.graph.clear();
//this gets rid of any methods you've attached to s.
s.graph.kill();
};
After clearing graph call refresh:
s.graph.clear();
s.refresh();
I'm using jquery
$("#graph").empty();