Link between two nodes - javascript
I've seen this Javascript code that connects several nodes that it gets from a JSON file.
I'm very new to Javascript and JSON and I'd like you to help me make it connect two nodes with one edge.
Thanks!
index.html
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node {
stroke: #fff;
stroke-width: 1.5px;
}
.link {
stroke: #999;
stroke-opacity: .6;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500;
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-120)
.linkDistance(30)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("miserables1.json", function(error, graph) {
force
.nodes(graph.nodes)
.links(graph.links)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
node.append("title")
.text(function(d) { return d.name; });
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});
</script>
miserables.json
{
"nodes":[
{"name":"Myriel","group":1},
{"name":"Napoleon","group":1},
{"name":"Mlle.Baptistine","group":1},
{"name":"Mme.Magloire","group":1},
{"name":"CountessdeLo","group":1},
{"name":"Geborand","group":1},
{"name":"Champtercier","group":1},
{"name":"Cravatte","group":1},
{"name":"Count","group":1},
{"name":"OldMan","group":1},
{"name":"Labarre","group":2},
{"name":"Valjean","group":2},
{"name":"Marguerite","group":3},
{"name":"Mme.deR","group":2},
{"name":"Isabeau","group":2},
{"name":"Gervais","group":2},
{"name":"Tholomyes","group":3},
{"name":"Listolier","group":3},
{"name":"Fameuil","group":3},
{"name":"Blacheville","group":3},
{"name":"Favourite","group":3},
{"name":"Dahlia","group":3},
{"name":"Zephine","group":3},
{"name":"Fantine","group":3},
{"name":"Mme.Thenardier","group":4},
{"name":"Thenardier","group":4},
{"name":"Cosette","group":5},
{"name":"Javert","group":4},
{"name":"Fauchelevent","group":0},
{"name":"Bamatabois","group":2},
{"name":"Perpetue","group":3},
{"name":"Simplice","group":2},
{"name":"Scaufflaire","group":2},
{"name":"Woman1","group":2},
{"name":"Judge","group":2},
{"name":"Champmathieu","group":2},
{"name":"Brevet","group":2},
{"name":"Chenildieu","group":2},
{"name":"Cochepaille","group":2},
{"name":"Pontmercy","group":4},
{"name":"Boulatruelle","group":6},
{"name":"Eponine","group":4},
{"name":"Anzelma","group":4},
{"name":"Woman2","group":5},
{"name":"MotherInnocent","group":0},
{"name":"Gribier","group":0},
{"name":"Jondrette","group":7},
{"name":"Mme.Burgon","group":7},
{"name":"Gavroche","group":8},
{"name":"Gillenormand","group":5},
{"name":"Magnon","group":5},
{"name":"Mlle.Gillenormand","group":5},
{"name":"Mme.Pontmercy","group":5},
{"name":"Mlle.Vaubois","group":5},
{"name":"Lt.Gillenormand","group":5},
{"name":"Marius","group":8},
{"name":"BaronessT","group":5},
{"name":"Mabeuf","group":8},
{"name":"Enjolras","group":8},
{"name":"Combeferre","group":8},
{"name":"Prouvaire","group":8},
{"name":"Feuilly","group":8},
{"name":"Courfeyrac","group":8},
{"name":"Bahorel","group":8},
{"name":"Bossuet","group":8},
{"name":"Joly","group":8},
{"name":"Grantaire","group":8},
{"name":"MotherPlutarch","group":9},
{"name":"Gueulemer","group":4},
{"name":"Babet","group":4},
{"name":"Claquesous","group":4},
{"name":"Montparnasse","group":4},
{"name":"Toussaint","group":5},
{"name":"Child1","group":10},
{"name":"Child2","group":10},
{"name":"Brujon","group":4},
{"name":"Mme.Hucheloup","group":8}
],
"links":[
{"source":1,"target":0,"value":1},
{"source":2,"target":0,"value":8},
{"source":3,"target":0,"value":10},
{"source":3,"target":2,"value":6},
{"source":4,"target":0,"value":1},
{"source":5,"target":0,"value":1},
{"source":6,"target":0,"value":1},
{"source":7,"target":0,"value":1},
{"source":8,"target":0,"value":2},
{"source":9,"target":0,"value":1},
{"source":11,"target":10,"value":1},
{"source":11,"target":3,"value":3},
{"source":11,"target":2,"value":3},
{"source":11,"target":0,"value":5},
{"source":12,"target":11,"value":1},
{"source":13,"target":11,"value":1},
{"source":14,"target":11,"value":1},
{"source":15,"target":11,"value":1},
{"source":17,"target":16,"value":4},
{"source":18,"target":16,"value":4},
{"source":18,"target":17,"value":4},
{"source":19,"target":16,"value":4},
{"source":19,"target":17,"value":4},
{"source":19,"target":18,"value":4},
{"source":20,"target":16,"value":3},
{"source":20,"target":17,"value":3},
{"source":20,"target":18,"value":3},
{"source":20,"target":19,"value":4},
{"source":21,"target":16,"value":3},
{"source":21,"target":17,"value":3},
{"source":21,"target":18,"value":3},
{"source":21,"target":19,"value":3},
{"source":21,"target":20,"value":5},
{"source":22,"target":16,"value":3},
{"source":22,"target":17,"value":3},
{"source":22,"target":18,"value":3},
{"source":22,"target":19,"value":3},
{"source":22,"target":20,"value":4},
{"source":22,"target":21,"value":4},
{"source":23,"target":16,"value":3},
{"source":23,"target":17,"value":3},
{"source":23,"target":18,"value":3},
{"source":23,"target":19,"value":3},
{"source":23,"target":20,"value":4},
{"source":23,"target":21,"value":4},
{"source":23,"target":22,"value":4},
{"source":23,"target":12,"value":2},
{"source":23,"target":11,"value":9},
{"source":24,"target":23,"value":2},
{"source":24,"target":11,"value":7},
{"source":25,"target":24,"value":13},
{"source":25,"target":23,"value":1},
{"source":25,"target":11,"value":12},
{"source":26,"target":24,"value":4},
{"source":26,"target":11,"value":31},
{"source":26,"target":16,"value":1},
{"source":26,"target":25,"value":1},
{"source":27,"target":11,"value":17},
{"source":27,"target":23,"value":5},
{"source":27,"target":25,"value":5},
{"source":27,"target":24,"value":1},
{"source":27,"target":26,"value":1},
{"source":28,"target":11,"value":8},
{"source":28,"target":27,"value":1},
{"source":29,"target":23,"value":1},
{"source":29,"target":27,"value":1},
{"source":29,"target":11,"value":2},
{"source":30,"target":23,"value":1},
{"source":31,"target":30,"value":2},
{"source":31,"target":11,"value":3},
{"source":31,"target":23,"value":2},
{"source":31,"target":27,"value":1},
{"source":32,"target":11,"value":1},
{"source":33,"target":11,"value":2},
{"source":33,"target":27,"value":1},
{"source":34,"target":11,"value":3},
{"source":34,"target":29,"value":2},
{"source":35,"target":11,"value":3},
{"source":35,"target":34,"value":3},
{"source":35,"target":29,"value":2},
{"source":36,"target":34,"value":2},
{"source":36,"target":35,"value":2},
{"source":36,"target":11,"value":2},
{"source":36,"target":29,"value":1},
{"source":37,"target":34,"value":2},
{"source":37,"target":35,"value":2},
{"source":37,"target":36,"value":2},
{"source":37,"target":11,"value":2},
{"source":37,"target":29,"value":1},
{"source":38,"target":34,"value":2},
{"source":38,"target":35,"value":2},
{"source":38,"target":36,"value":2},
{"source":38,"target":37,"value":2},
{"source":38,"target":11,"value":2},
{"source":38,"target":29,"value":1},
{"source":39,"target":25,"value":1},
{"source":40,"target":25,"value":1},
{"source":41,"target":24,"value":2},
{"source":41,"target":25,"value":3},
{"source":42,"target":41,"value":2},
{"source":42,"target":25,"value":2},
{"source":42,"target":24,"value":1},
{"source":43,"target":11,"value":3},
{"source":43,"target":26,"value":1},
{"source":43,"target":27,"value":1},
{"source":44,"target":28,"value":3},
{"source":44,"target":11,"value":1},
{"source":45,"target":28,"value":2},
{"source":47,"target":46,"value":1},
{"source":48,"target":47,"value":2},
{"source":48,"target":25,"value":1},
{"source":48,"target":27,"value":1},
{"source":48,"target":11,"value":1},
{"source":49,"target":26,"value":3},
{"source":49,"target":11,"value":2},
{"source":50,"target":49,"value":1},
{"source":50,"target":24,"value":1},
{"source":51,"target":49,"value":9},
{"source":51,"target":26,"value":2},
{"source":51,"target":11,"value":2},
{"source":52,"target":51,"value":1},
{"source":52,"target":39,"value":1},
{"source":53,"target":51,"value":1},
{"source":54,"target":51,"value":2},
{"source":54,"target":49,"value":1},
{"source":54,"target":26,"value":1},
{"source":55,"target":51,"value":6},
{"source":55,"target":49,"value":12},
{"source":55,"target":39,"value":1},
{"source":55,"target":54,"value":1},
{"source":55,"target":26,"value":21},
{"source":55,"target":11,"value":19},
{"source":55,"target":16,"value":1},
{"source":55,"target":25,"value":2},
{"source":55,"target":41,"value":5},
{"source":55,"target":48,"value":4},
{"source":56,"target":49,"value":1},
{"source":56,"target":55,"value":1},
{"source":57,"target":55,"value":1},
{"source":57,"target":41,"value":1},
{"source":57,"target":48,"value":1},
{"source":58,"target":55,"value":7},
{"source":58,"target":48,"value":7},
{"source":58,"target":27,"value":6},
{"source":58,"target":57,"value":1},
{"source":58,"target":11,"value":4},
{"source":59,"target":58,"value":15},
{"source":59,"target":55,"value":5},
{"source":59,"target":48,"value":6},
{"source":59,"target":57,"value":2},
{"source":60,"target":48,"value":1},
{"source":60,"target":58,"value":4},
{"source":60,"target":59,"value":2},
{"source":61,"target":48,"value":2},
{"source":61,"target":58,"value":6},
{"source":61,"target":60,"value":2},
{"source":61,"target":59,"value":5},
{"source":61,"target":57,"value":1},
{"source":61,"target":55,"value":1},
{"source":62,"target":55,"value":9},
{"source":62,"target":58,"value":17},
{"source":62,"target":59,"value":13},
{"source":62,"target":48,"value":7},
{"source":62,"target":57,"value":2},
{"source":62,"target":41,"value":1},
{"source":62,"target":61,"value":6},
{"source":62,"target":60,"value":3},
{"source":63,"target":59,"value":5},
{"source":63,"target":48,"value":5},
{"source":63,"target":62,"value":6},
{"source":63,"target":57,"value":2},
{"source":63,"target":58,"value":4},
{"source":63,"target":61,"value":3},
{"source":63,"target":60,"value":2},
{"source":63,"target":55,"value":1},
{"source":64,"target":55,"value":5},
{"source":64,"target":62,"value":12},
{"source":64,"target":48,"value":5},
{"source":64,"target":63,"value":4},
{"source":64,"target":58,"value":10},
{"source":64,"target":61,"value":6},
{"source":64,"target":60,"value":2},
{"source":64,"target":59,"value":9},
{"source":64,"target":57,"value":1},
{"source":64,"target":11,"value":1},
{"source":65,"target":63,"value":5},
{"source":65,"target":64,"value":7},
{"source":65,"target":48,"value":3},
{"source":65,"target":62,"value":5},
{"source":65,"target":58,"value":5},
{"source":65,"target":61,"value":5},
{"source":65,"target":60,"value":2},
{"source":65,"target":59,"value":5},
{"source":65,"target":57,"value":1},
{"source":65,"target":55,"value":2},
{"source":66,"target":64,"value":3},
{"source":66,"target":58,"value":3},
{"source":66,"target":59,"value":1},
{"source":66,"target":62,"value":2},
{"source":66,"target":65,"value":2},
{"source":66,"target":48,"value":1},
{"source":66,"target":63,"value":1},
{"source":66,"target":61,"value":1},
{"source":66,"target":60,"value":1},
{"source":67,"target":57,"value":3},
{"source":68,"target":25,"value":5},
{"source":68,"target":11,"value":1},
{"source":68,"target":24,"value":1},
{"source":68,"target":27,"value":1},
{"source":68,"target":48,"value":1},
{"source":68,"target":41,"value":1},
{"source":69,"target":25,"value":6},
{"source":69,"target":68,"value":6},
{"source":69,"target":11,"value":1},
{"source":69,"target":24,"value":1},
{"source":69,"target":27,"value":2},
{"source":69,"target":48,"value":1},
{"source":69,"target":41,"value":1},
{"source":70,"target":25,"value":4},
{"source":70,"target":69,"value":4},
{"source":70,"target":68,"value":4},
{"source":70,"target":11,"value":1},
{"source":70,"target":24,"value":1},
{"source":70,"target":27,"value":1},
{"source":70,"target":41,"value":1},
{"source":70,"target":58,"value":1},
{"source":71,"target":27,"value":1},
{"source":71,"target":69,"value":2},
{"source":71,"target":68,"value":2},
{"source":71,"target":70,"value":2},
{"source":71,"target":11,"value":1},
{"source":71,"target":48,"value":1},
{"source":71,"target":41,"value":1},
{"source":71,"target":25,"value":1},
{"source":72,"target":26,"value":2},
{"source":72,"target":27,"value":1},
{"source":72,"target":11,"value":1},
{"source":73,"target":48,"value":2},
{"source":74,"target":48,"value":2},
{"source":74,"target":73,"value":3},
{"source":75,"target":69,"value":3},
{"source":75,"target":68,"value":3},
{"source":75,"target":25,"value":3},
{"source":75,"target":48,"value":1},
{"source":75,"target":41,"value":1},
{"source":75,"target":70,"value":1},
{"source":75,"target":71,"value":1},
{"source":76,"target":64,"value":1},
{"source":76,"target":65,"value":1},
{"source":76,"target":66,"value":1},
{"source":76,"target":63,"value":1},
{"source":76,"target":62,"value":1},
{"source":76,"target":48,"value":1},
{"source":76,"target":58,"value":1}
]
}
Related
Drag, drop and fix a node in D3JS
I have a HTML File to display graphs using D3JS. The JSFiddle is in this link here. I know that I must use the function to enable the fixing of node position on dragging and dropping: var drag = force.drag() .on("dragstart", dragstart); function dragstart(d) { d3.select(this).classed("fixed", d.fixed = true); } However, on dragging and dropping a node, I am unable to fix the position. I want the same functionality as shown in this link .I don't want the node to revert to its original position. How do I change it?
From this example : http://bl.ocks.org/mbostock/3750558 You need to add a call to drag function : var drag = force.drag() .on("dragstart", dragstart); Which is the following : function dragstart(d) { d3.select(this).classed("fixed", d.fixed = true); } The key point is setting d.fixed to true. EDIT In your fiddle you weren't calling node_drag. So you need to call that on the nodes like so : var node = gnodes.append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { thelistofcolors[d.group] = color(d.group); return color(d.group); }) .call(node_drag); // <<<<<<<this line And then change the tick to a function so you can call it later : force.on("tick", tick); function tick() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); gnodes.attr("transform", function(d) { return 'translate(' + [d.x, d.y] + ')'; }); }; Updated fiddle with all data showing (not filtered on click) : https://jsfiddle.net/vgy1s8k3/4/
The solution is to set a 'fixed' node property to true on dragstart, this will allow to append the position. <!DOCTYPE html> <html> <head> <script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script> <style> .node { stroke: #fff; stroke-width: 1.5px; } .link { stroke: #999; stroke-opacity: .6; } </style> </head> <body> <script> var width = 1280, height = 960; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); d3.json("graph.json", function(error, graph) { if (error) throw error; force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll("graph.link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); var node = svg.selectAll("graph.node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { return color(d.fill); }) .call(force.drag); var drag = force.drag() .on("dragstart", dragstart); function dragstart(d) { d.fixed = true; } node.append("title") .text(function(d) { return d.name }); force.on("tick", tick); function tick() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); }; }); </script> </body> </html>
Read Data from JSON file using d3.js
I am new to d3.js and I am trying to reproduce the example B is for breaking links in this tutorial. As you can see in the jsfiddle of this example, the data is read from a <script type="application/json" id="mis"> tag, but what I want is to read it from a different file. I used the d3.json() function as suggested in this Force-Layout example, but when I added the threshold slider which is supposed to break my links, nothing happens. When I ran the console, it gave me the following error : Uncaught TypeError: Cannot read property 'splice' of undefined threshold # index.html:82 onchange # index.html:101 This is my code : output.json The file output.json is in this link. index.html <!DOCTYPE html> <meta charset="utf-8"> <style> .node { stroke: #fff; stroke-width: 1.5px; } .link { stroke: #999; stroke-opacity: .6; } h3 { color: #1ABC9C; text-align:center; font-style: italic; font-size: 14px; font-family: "Helvetica"; } </style> <body> <script src="//d3js.org/d3.v3.min.js"></script> <script> var width = 960, height = 500; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var graph = d3.json("output.json", function(error, graph) { if (error) throw error; graphRec=JSON.parse(JSON.stringify(graph)); force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { return color(d.group); }) .call(force.drag); node.append("title") .text(function(d) { return d.name; }); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); }); //adjust threshold function threshold(thresh) { graph.links.splice(0, graph.links.length); for (var i = 0; i < graphRec.links.length; i++) { if (graphRec.links[i].value > thresh) {graph.links.push(graphRec.links[i]);} } restart(); } //Restart the visualisation after any node and link changes function restart() { link = link.data(graph.links); link.exit().remove(); link.enter().insert("line", ".node").attr("class", "link"); node = node.data(graph.nodes); node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag); force.start(); } </script> <form> <h3> Link threshold 0 <input type="range" id="thersholdSlider" name="points" value = 0 min="0" max="10" onchange="threshold(this.value)"> 10 </h3> </form> What did I do wrong ? And how can I fix it ? Thanks!
I could not find any bugs in your code. The only problem I could find is that the variable name graph used twice. var graph = d3.json("output.json", function(error, graph) { --------------------- --------------------- }); Edit: Try this code. var graphRec, node, link; d3.json("output.json", function(error, graph) { if (error) throw error; graph = JSON.parse(JSON.stringify(graph)); force .nodes(graph.nodes) .links(graph.links) .start(); graphRec = graph; link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { return color(d.group); }) .call(force.drag); ------------------------ ------------------------ }); //adjust threshold function threshold(thresh) { graphRec.links.splice(0, graphRec.links.length); for (var i = 0; i < graphRec.links.length; i++) { if (graphRec.links[i].value > thresh) {graphRec.links.push(graphRec.links[i]);} } restart(); } //Restart the visualisation after any node and link changes function restart() { link = link.data(graphRec.links); link.exit().remove(); link.enter().insert("line", ".node").attr("class", "link"); node = node.data(graphRec.nodes); node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag); force.start(); } Working Code Snippet. var width = 960, height = 500; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var graph = {"nodes":[{"name":"DOU,_H.","group":1},{"name":"QUONIAM","group":1},{"name":"DA_SILV","group":1},{"name":"GUIMARA","group":1},{"name":"SOARES_","group":0}],"links":[{"source":1,"target":0,"value":19,"oriented":false,"date":null},{"source":1,"target":2,"value":2,"oriented":false,"date":null},{"source":1,"target":3,"value":1,"oriented":false,"date":null},{"source":1,"target":4,"value":1,"oriented":false,"date":null},{"source":1,"target":3,"value":2,"oriented":false,"date":null}]}; graph = JSON.parse(JSON.stringify(graph)); force .nodes(graph.nodes) .links(graph.links) .start(); graphRec = graph; var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { return color(d.group); }) .call(force.drag); node.append("title") .text(function(d) { return d.name; }); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); //adjust threshold function threshold(thresh) { graph.links.splice(0, graph.links.length); for (var i = 0; i < graphRec.links.length; i++) { if (graphRec.links[i].value > thresh) { graph.links.push(graphRec.links[i]); } } restart(); } //Restart the visualisation after any node and link changes function restart() { link = link.data(graph.links); link.exit().remove(); link.enter().insert("line", ".node").attr("class", "link"); node = node.data(graph.nodes); node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag); force.start(); } .node { stroke: #fff; stroke-width: 1.5px; } .link { stroke: #999; stroke-opacity: .6; } h3 { color: #1ABC9C; text-align:center; font-style: italic; font-size: 14px; font-family: "Helvetica"; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <form> <h3> Link threshold 0 <input type="range" id="thersholdSlider" name="points" value = 0 min="0" max="10" onchange="threshold(this.value)"> 10 </h3> </form>
Zoom for graph in D3
I have javascript code that draws a graph using data stored in json file. <!DOCTYPE html xmlns:xlink="http://www.w3.org/1999/xlink"> <meta charset="utf-8"> <style> // style here </style> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <div id="animviz"></div> <script> var vv = window, w = vv.innerWidth, h = vv.innerHeight; var x = d3.scale.linear() .domain([0, w]) .range([0, w]); var y = d3.scale.linear() .domain([0, h]) .range([h, 0]); var svg = d3.select("#animviz") .append("svg") .attr("width", w) .attr("height", h) .append("g") var color = d3.scale.category10(); var force = d3.layout.force() .charge(-200) .linkDistance(50) .size([w, h]); d3.json("post000.json", function(error, graph) { force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") var myMouseoverFunction = function() { var circle = d3.select(this); circle.transition().duration(100) .attr("r", 20 ) node.append("title") .text(function(d) { return d.name}); } var myMouseoutFunction = function() { var circle = d3.select(this); circle.transition().duration(500) .attr("r", 10 ); } var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 10) .attr("transform", transform) .style("fill", function(d) { return color(d.group); }) .call(force.drag) .on("mouseover", myMouseoverFunction) .on("mouseout", myMouseoutFunction); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); }); </script> </body> However I can't zoom in or out this graph in a browser. I planned to use similar example from documentation; however, in my case I load data from post000.json using d3.json that is asynchronous and I'm not sure how I can access this data when it's loaded to pass it as input to zoom function. How can I draw a graph that I can zoom in with data stored in json?
Here is code that works for me: <!DOCTYPE html xmlns:xlink="http://www.w3.org/1999/xlink"> <meta charset="utf-8"> <style> // style here </style> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <div id="animviz"></div> <script> d3.json("post000.json", function(error, graph) { var vv = window, w = vv.innerWidth, h = vv.innerHeight; var svg = d3.select("#animviz") .append("svg") .attr("width", w) .attr("height", h) .append("g") .call(d3.behavior.zoom().scaleExtent([0, 8]).on("zoom", zoom)) .append("g"); var color = d3.scale.category10(); var force = d3.layout.force() .charge(-200) .linkDistance(50) .size([w, h]); force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .attr("transform", function(d) { return "translate(" + d + ")"; }); function zoom() { svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } var myMouseoverFunction = function() { var circle = d3.select(this); circle.transition().duration(100) .attr("r", 20 ) node.append("title") .text(function(d) { return d.name}); } var myMouseoutFunction = function() { var circle = d3.select(this); circle.transition().duration(500) .attr("r", 10 ); } var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 10) .style("fill", function(d) { return color(d.group); }) .call(force.drag) .on("mouseover", myMouseoverFunction) .on("mouseout", myMouseoutFunction); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); }); </script> </body>
How to add custom colors in D3 nodes of a graph
I am using D3 api for a graph where a couple of nodes are forming from a parent node i want to color the nodes of the whole graph in a manner that each parent node has a fixed color and the child nodes has different color i.e a root node always have red color and the left child is blue and the right one is green and if only one child is there it is green .I am using this api ,, <!DOCTYPE html> <html> <head> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.27.1"></script> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?1.27.1"></script> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?1.27.1"></script> <style type="text/css"> line.link { stroke: #ccc; } circle.node { fill: #000; stroke: #fff; stroke-width: 1.5px; } </style> </head> <body> <script type="text/javascript"> var w = 960, h = 500, r = d3.scale.sqrt().domain([0, 20000]).range([0, 20]); var force = d3.layout.force() .gravity(.01) .charge(-120) .linkDistance(60) .size([w, h]); var svg = d3.select("body").append("svg:svg") .attr("width", w) .attr("height", h); d3.xml("flare.xml", "application/xml", function(xml) { var nodes = self.nodes = d3.select(xml).selectAll("*")[0], links = self.links = nodes.slice(1).map(function(d) { return {source: d, target: d.parentNode}; }); force .nodes(nodes) .links(links) .start(); var link = svg.selectAll("line.link") .data(links) .enter().append("svg:line") .attr("class", "link") .attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); var node = svg.selectAll("circle.node") .data(nodes) .enter().append("svg:circle") .attr("class", "node") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .attr("r", function(d) { return r(d.textContent) || 5; }) .call(force.drag); force.on("tick", function() { nodes[0].x = w / 2; nodes[0].y = h / 2; link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); }); </script> </body> </html> can anyone help me
SVG has its own CSS properties, one of which being fill. It sets the fill color of an SVG element. Here is how you use it with D3: var node = svg.selectAll("circle.node") .data(nodes) .enter().append("svg:circle") .style("fill", function (d) { return '#1f77b4'; }) .attr("class", "node") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .attr("r", function(d) { return r(d.textContent) || 5; }) .call(force.drag); Here the color value (#1f77b4) will be the same for all nodes. If you want to color your nodes with a specific algorithm, D3 ships with predefined categorical color scales. Edit: Here is a related SO question. One of its answers has a good custom ordinal color scale example.
Labels / text on the nodes of a D3 force directed graph
I still not understanding why the code bellow does not display its labels / text... I have defined the css and set the attribute like the title when the move is over the node: Json: { "nodes":[ {"name":"t1","group":1}, {"name":"t2","group":1}, {"name":"t3","group":1}, {"name":"t4","group":1}, {"name":"hate","group":2}, {"name":"good","group":2}, {"name":"aiport","group":3}, {"name":"flight","group":3} ], "links":[ {"source":0,"target":4,"value":4}, {"source":0,"target":5,"value":4}, {"source":1,"target":4,"value":4}, {"source":2,"target":5,"value":4}, {"source":3,"target":5,"value":4}, {"source":4,"target":6,"value":4}, {"source":5,"target":6,"value":4}, {"source":5,"target":7,"value":4} ] } Code: <!DOCTYPE html> <meta charset="utf-8"> <style> .node { fill: #555; stroke: #999; stroke-width: 1.5px; } .link { stroke: #999; stroke-opacity: .6; } </style> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <script> var width = 1024, height = 768; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); d3.json("data.json", function(error, graph) { force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll("line.link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); var node = svg.selectAll("circle.node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { return color(d.group); }) .call(force.drag); node.append("title") .text(function(d) { return d.name; }); node.append("text") .text(function(d) { return d.name; }); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }); }); </script> </body> </html>
You are adding the text element inside the circle element - try running your code and have a look at the svg with the DOM inspector. I'm not sure text is allowed there. Instead add the text elements separately - like another rendering of the nodes: var texts = svg.selectAll("text.label") .data(graph.nodes) .enter().append("text") .attr("class", "label") .attr("fill", "black") .text(function(d) { return d.name; }); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); texts.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); });
Another option would be to add both circle and text elements inside a g container element as shown below: var container = svg.selectAll("g.node").data(graph.nodes).enter().append("g") .attr("class", "node") .attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; }).call(force.drag); container.append("circle") .attr("r", 5) .style("fill", color); container.append("text") .style("text-anchor", "middle") .text(function (d) { return d.name; }); Here you can play with a working jsfiddle: http://jsfiddle.net/vfu78/16/