Skip to content

Instantly share code, notes, and snippets.

@ngminhtrung
Last active May 8, 2018 03:19
Show Gist options
  • Save ngminhtrung/46ba58b24614d24dc085fc404739aec3 to your computer and use it in GitHub Desktop.
Save ngminhtrung/46ba58b24614d24dc085fc404739aec3 to your computer and use it in GitHub Desktop.
D3js v4 - Modifying a Force Layout

Original block:

Ví dụ này minh họa cách để thêm/ bớt các nodes/ links trong một layout force-directed.

  • Đầu tiên màn hình chỉ hiện 3 điểm A, B và C.
  • Sau 5 giây, 3 điểm trên được nối lại với nhau.
  • Tiếp sau đó, điểm C bị xóa đi cùng với đường nối A-C, và B-C.
  • Tiếp sau đó, điểm C được thêm vào lại trong nhóm, đường nối A-C và B-C được khôi phục.
  • 2 bước cuối ở trên được lặp đi lặp lại.

Ví dụ này sử dụng "general update pattern" để join data. Một mục khác có thể tham khảo là "modifying a force layout with transitions".

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://d3js.org/d3.v4.min.js"></script>
<title>Document</title>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
color = d3.scaleOrdinal(d3.schemeCategory10);
var a = { id: "a" },
b = { id: "b" },
c = { id: "c" },
nodes = [a, b, c],
links = [];
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-1000))
.force("link", d3.forceLink(links).distance(200))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaTarget(1)
.on("tick", ticked);
var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link"),
node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");
restart();
d3.timeout(function () {
links.push({ source: a, target: b }); // Add a-b.
links.push({ source: b, target: c }); // Add b-c.
links.push({ source: c, target: a }); // Add c-a.
restart();
}, 5000);
d3.interval(function () {
nodes.pop(); // Remove c.
links.pop(); // Remove c-a.
links.pop(); // Remove b-c.
restart();
}, 2000, d3.now());
d3.interval(function () {
nodes.push(c); // Re-add c.
links.push({ source: b, target: c }); // Re-add b-c.
links.push({ source: c, target: a }); // Re-add c-a.
restart();
}, 2000, d3.now() + 1000);
function restart() {
// Apply the general update pattern to the nodes.
node = node.data(nodes, function (d) { return d.id; });
node.exit().remove();
node = node.enter().append("circle").attr("fill", function (d) { return color(d.id); }).attr("r", 8).merge(node);
// Apply the general update pattern to the links.
link = link.data(links, function (d) { return d.source.id + "-" + d.target.id; });
link.exit().remove();
link = link.enter().append("line").merge(link);
// Update and restart the simulation.
simulation.nodes(nodes);
simulation.force("link").links(links);
simulation.alpha(1).restart();
}
function ticked() {
console.count("alpha", simulation.alpha());
console.count("alphaTarget", simulation.alphaTarget());
node.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; })
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; });
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment