Reputation: 1416
just getting started with D3. I am currently doing the network trading project which requires me to join nodes with other nodes depends the json file.
My json file looks like this.
{
"nodes": [
{
"id": "site01",
"x": 317.5,
"y": 282.5
},
{
"id": "site02",
"x": 112,
"y": 47
},
{
"id": "site03",
"x": 69.5,
"y": 287
},
]
"links": [
{
"node01": "site01",
"node02": "site02",
"amount": 170
},
{
"node01": "site01",
"node02": "site03",
"amount": 100
},
{
"node01": "site02",
"node02": "site03",
"amount": 70
},
]
}
What I am able to do write now is to plot the position of all the sites in nodes.
Here is my code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script type="text/javascript">
var w = 1200;
var h = 800;
var svg = d3.select("body").append("svg").attr("width",w).attr("height", h);
var lines = svg.attr("class", "line")
d3.json("data.json", function(error, data) {
console.log(data);
var circles = svg.selectAll("foo")
.data(data.nodes)
.enter()
.append("circle")
.attr("cx", function(d) {return d.x;})
.attr("cy", function(d) {return d.y;})
.attr("r", 20)
.append("title") // For hover effect
.text(function(d) { return "The site is " + d.id; });
var lines = svg.selectAll("foo")
.data(data.links)
.enter()
.append("line")
.attr("x1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cx")
})
.attr("x2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cx")
})
.attr("y1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cy")
})
.attr("y2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cy")
})
.attr("stroke", "gray");
circles.raise();
});
</script>
</body>
</html>
My question is how can I possibly draw a line between 2 sites as describe in "links" in my json file. Also, how can I change the radius of the circle based on the amount describe in "links". For example, if site01 and site02 has a link, therefore the radius of those 2 nodes would be the same.
Edit - change to current version
Thank you,
Upvotes: 1
Views: 1292
Reputation: 102188
When I first read your question's title I thought "ok, OP wants a force directed chart", and that's why I asked about D3 v4.x in the comments...
However, it seems to me that you don't want a force directed: you already have the circles' positions. You just want to link them.
That being the case, you can filter the circles' selection to get the lines' x1
, x2
, y1
and y2
:
var lines = svg.selectAll("foo")
.data(data.links)
.enter()
.append("line")
.attr("x1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cx")
})
.attr("x2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cx")
})
.attr("y1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cy")
})
.attr("y2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cy")
})
.attr("stroke", "gray");
Here is the demo using your code and that selection for the lines:
var data = {
"nodes": [{
"id": "site01",
"x": 317.5,
"y": 282.5
}, {
"id": "site02",
"x": 112,
"y": 47
}, {
"id": "site03",
"x": 69.5,
"y": 287
}],
"links": [{
"node01": "site01",
"node02": "site02",
"amount": 170
}, {
"node01": "site01",
"node02": "site03",
"amount": 100
}, {
"node01": "site02",
"node02": "site03",
"amount": 70
}]
};
var w = 400;
var h = 320;
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
var lines = svg.attr("class", "line")
var circles = svg.selectAll("foo")
.data(data.nodes)
.enter()
.append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", 20);
circles.append("title")
.text(function(d) {
return "The site is " + d.id;
});
var lines = svg.selectAll("foo")
.data(data.links)
.enter()
.append("line")
.attr("x1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cx")
})
.attr("x2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cx")
})
.attr("y1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cy")
})
.attr("y2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cy")
})
.attr("stroke", "gray");
<script src="https://d3js.org/d3.v4.min.js"></script>
And here the same code, but with the lines behind the circles:
var data = {
"nodes": [{
"id": "site01",
"x": 317.5,
"y": 282.5
}, {
"id": "site02",
"x": 112,
"y": 47
}, {
"id": "site03",
"x": 69.5,
"y": 287
}],
"links": [{
"node01": "site01",
"node02": "site02",
"amount": 170
}, {
"node01": "site01",
"node02": "site03",
"amount": 100
}, {
"node01": "site02",
"node02": "site03",
"amount": 70
}]
};
var w = 400;
var h = 320;
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
var lines = svg.attr("class", "line")
var circles = svg.selectAll("foo")
.data(data.nodes)
.enter()
.append("circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", 20);
circles.append("title")
.text(function(d) {
return "The site is " + d.id;
});
var lines = svg.selectAll("foo")
.data(data.links)
.enter()
.append("line")
.attr("x1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cx")
})
.attr("x2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cx")
})
.attr("y1", function(d) {
return circles.filter(function(e) {
return e.id === d.node01
}).attr("cy")
})
.attr("y2", function(d) {
return circles.filter(function(e) {
return e.id === d.node02
}).attr("cy")
})
.attr("stroke", "gray");
circles.raise();
<script src="https://d3js.org/d3.v4.min.js"></script>
Upvotes: 1