Skip to content

Instantly share code, notes, and snippets.

@denisemauldin
Last active July 11, 2018 00:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save denisemauldin/d71c217e53ee400e537dc32a901bc0c6 to your computer and use it in GitHub Desktop.
Save denisemauldin/d71c217e53ee400e537dc32a901bc0c6 to your computer and use it in GitHub Desktop.
Add and remove nodes
license: mit

Click to add nodes! Nodes near the cursor will be linked to the new node. Clicking an existing node will remove it.

This is an extension of this example, adding the capability of removing nodes by clicking them. This means that dragging is no longer supported.

forked from tgk's block: Add and remove nodes

forked from juzkev's block: Add and remove nodes

<!DOCTYPE html>
<meta charset="utf-8">
<style>
rect {
fill: none;
pointer-events: all;
}
.node {
fill: #000;
}
.cursor {
fill: none;
stroke: brown;
pointer-events: none;
}
.link {
stroke: #999;
}
</style>
<body>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500;
var fill = d3.schemeCategory20;
var links = [];
var nodes = [{}]
var force = d3.forceSimulation()
.nodes(nodes) // initialize with a single node
.force("link", d3.forceLink(links).distance(200))
.force("charge", d3.forceManyBody().strength(-1000))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaTarget(1)
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.on("mousemove", mousemove)
.on("mousedown", mousedownCanvas);
svg.append("rect")
.attr("width", width)
.attr("height", height);
var node = svg.selectAll(".node"),
link = svg.selectAll(".link");
var cursor = svg.append("circle")
.attr("r", 30)
.attr("transform", "translate(-100,-100)")
.attr("class", "cursor");
restart();
function mousemove() {
cursor.attr("transform", "translate(" + d3.mouse(this) + ")");
}
function mousedownCanvas() {
console.log("mouseDownCanvas", this)
var point = d3.mouse(this),
node = {x: point[0], y: point[1]};
console.log("mouseDownCanvas", node)
// add links to any nearby nodes
nodes.forEach(function(target) {
console.log("target", target)
var x = target.x - node.x,
y = target.y - node.y;
if (Math.sqrt(x * x + y * y) < 30) {
console.log("adding link", node, target)
links.push({source: node, target: target});
}
});
nodes.push(node);
restart();
}
function mousedownNode(d, i) {
nodes.splice(i, 1);
links = links.filter(function(l) {
return l.source !== d && l.target !== d;
});
d3.event.stopPropagation();
restart();
}
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("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
function restart() {
node = node.data(nodes, function(d) { return d.id});
node.exit()
.remove();
node.enter().append("circle", ".cursor")
.attr("class", "node")
.attr("r", 5)
.on("mousedown", mousedownNode)
.merge(node);
link = link.data(links, function(d) { return d.source.id + "-" + d.target.id; });
link.exit()
.remove();
link.enter().append("line", ".node")
.attr("class", "link")
.merge(link);
// Update and restart the simulation.
force.nodes(nodes);
force.force("link").links(links);
force.alpha(1).restart();
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment